- remove input/output fields, input tracking removed.
- remove state fields, the validate function now called
on every statechange.
- add an explicit 'create' function.
Add in code to build vertex program to implement current t&l state. Still
disabled, but turn on with a #define in t_vp_build.h.
struct gl_fragment_program_state FragmentProgram; /**< GL_NV_fragment_program */
struct gl_ati_fragment_shader_state ATIFragmentShader; /**< GL_ATI_fragment_shader */
+ struct fragment_program _TexEnvProgram; /**< Texture state as fragment program */
+ struct vertex_program _TnlProgram; /**< Fixed func TNL state as vertex program */
+
struct gl_occlusion_state Occlusion; /**< GL_ARB_occlusion_query */
struct gl_shader_objects_state ShaderObjects; /* GL_ARB_shader_objects */
tnl/t_save_api.c \
tnl/t_save_loopback.c \
tnl/t_save_playback.c \
- tnl/t_vb_cull.c \
- tnl/t_vb_fog.c \
- tnl/t_vb_light.c \
- tnl/t_vb_normals.c \
- tnl/t_vb_points.c \
+ tnl/t_vb_arbprogram.c \
tnl/t_vb_program.c \
tnl/t_vb_render.c \
tnl/t_vb_texgen.c \
tnl/t_vb_texmat.c \
tnl/t_vb_vertex.c \
+ tnl/t_vb_cull.c \
+ tnl/t_vb_fog.c \
+ tnl/t_vb_light.c \
+ tnl/t_vb_normals.c \
+ tnl/t_vb_points.c \
+ tnl/t_vp_build.c \
tnl/t_vertex.c \
tnl/t_vertex_c.c \
tnl/t_vertex_codegen.c \
tnl/t_vtx_eval.c \
tnl/t_vtx_exec.c
+
+
SHADER_SOURCES = \
shader/arbfragparse.c \
shader/arbprogparse.c \
struct tnl_prim prim;
FLUSH_CURRENT( ctx, 0 );
- if (tnl->pipeline.build_state_changes)
- _tnl_validate_pipeline( ctx );
-
_tnl_vb_bind_arrays( ctx, 0, max_index );
tnl->vb.Primitive = &prim;
tnl->vb.Elts = (GLuint *)indices;
- if (ctx->Array.LockCount)
- tnl->Driver.RunPipeline( ctx );
- else {
- /* The lower 16 bits represent the conventional arrays while the
- * upper 16 bits represent the generic arrays. OR those bits
- * together to indicate which vertex attribs are in effect.
- */
- GLuint enabledArrays = ctx->Array._Enabled | (ctx->Array._Enabled >> 16);
- /* Note that arrays may have changed before/after execution.
- */
- tnl->pipeline.run_input_changes |= enabledArrays & 0xffff;
- tnl->Driver.RunPipeline( ctx );
- tnl->pipeline.run_input_changes |= enabledArrays & 0xffff;
- }
+ tnl->Driver.RunPipeline( ctx );
}
GET_CURRENT_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint thresh = (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES) ? 30 : 10;
- GLuint enabledArrays;
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(NULL, "_tnl_DrawArrays %d %d\n", start, count);
if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
return;
- if (tnl->pipeline.build_state_changes)
- _tnl_validate_pipeline( ctx );
-
assert(!ctx->CompileFlag);
if (!ctx->Array.LockCount && (GLuint) count < thresh) {
tnl->vb.Primitive[0].count = nr + minimum;
tnl->vb.PrimitiveCount = 1;
- /* The lower 16 bits represent the conventional arrays while the
- * upper 16 bits represent the generic arrays. OR those bits
- * together to indicate which vertex attribs are in effect.
- */
- enabledArrays = ctx->Array._Enabled | (ctx->Array._Enabled >> 16);
- /* Note that arrays may have changed before/after execution.
- */
- tnl->pipeline.run_input_changes |= enabledArrays;
tnl->Driver.RunPipeline( ctx );
- tnl->pipeline.run_input_changes |= enabledArrays;
}
}
}
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint inputs = tnl->pipeline.inputs;
struct tnl_vertex_arrays *tmp = &tnl->array_inputs;
GLuint i, index;
}
/* use conventional arrays... */
else if (index == VERT_ATTRIB_POS) {
- if (inputs & _TNL_BIT_POS) {
- _tnl_import_vertex( ctx, 0, 0 );
- tmp->Obj.count = VB->Count;
- VB->AttribPtr[_TNL_ATTRIB_POS] = &tmp->Obj;
- }
+ _tnl_import_vertex( ctx, 0, 0 );
+ tmp->Obj.count = VB->Count;
+ VB->AttribPtr[_TNL_ATTRIB_POS] = &tmp->Obj;
}
else if (index == VERT_ATTRIB_NORMAL) {
- if (inputs & _TNL_BIT_NORMAL) {
- _tnl_import_normal( ctx, 0, 0 );
- tmp->Normal.count = VB->Count;
- VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &tmp->Normal;
- }
+ _tnl_import_normal( ctx, 0, 0 );
+ tmp->Normal.count = VB->Count;
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &tmp->Normal;
}
else if (index == VERT_ATTRIB_COLOR0) {
- if (inputs & _TNL_BIT_COLOR0) {
- _tnl_import_color( ctx, 0, 0 );
- tmp->Color.count = VB->Count;
- VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &tmp->Color;
- }
+ _tnl_import_color( ctx, 0, 0 );
+ tmp->Color.count = VB->Count;
+ VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &tmp->Color;
}
else if (index == VERT_ATTRIB_COLOR1) {
- if (inputs & _TNL_BIT_COLOR1) {
- _tnl_import_secondarycolor( ctx, 0, 0 );
- tmp->SecondaryColor.count = VB->Count;
- VB->AttribPtr[_TNL_ATTRIB_COLOR1] = &tmp->SecondaryColor;
- }
+ _tnl_import_secondarycolor( ctx, 0, 0 );
+ tmp->SecondaryColor.count = VB->Count;
+ VB->AttribPtr[_TNL_ATTRIB_COLOR1] = &tmp->SecondaryColor;
}
else if (index == VERT_ATTRIB_FOG) {
- if (inputs & _TNL_BIT_FOG) {
- _tnl_import_fogcoord( ctx, 0, 0 );
- tmp->FogCoord.count = VB->Count;
- VB->AttribPtr[_TNL_ATTRIB_FOG] = &tmp->FogCoord;
- }
+ _tnl_import_fogcoord( ctx, 0, 0 );
+ tmp->FogCoord.count = VB->Count;
+ VB->AttribPtr[_TNL_ATTRIB_FOG] = &tmp->FogCoord;
}
else if (index >= VERT_ATTRIB_TEX0 && index <= VERT_ATTRIB_TEX7) {
- if (inputs & _TNL_BITS_TEX_ANY) {
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (inputs & _TNL_BIT_TEX(i)) {
- _tnl_import_texcoord( ctx, i, GL_FALSE, GL_FALSE );
- tmp->TexCoord[i].count = VB->Count;
- VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] = &tmp->TexCoord[i];
- }
- }
- }
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ _tnl_import_texcoord( ctx, i, GL_FALSE, GL_FALSE );
+ tmp->TexCoord[i].count = VB->Count;
+ VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] = &tmp->TexCoord[i];
+ }
}
}
/* odd-ball vertex attributes */
- if (inputs & _TNL_BIT_INDEX) {
+ {
_tnl_import_index( ctx, 0, 0 );
tmp->Index.count = VB->Count;
VB->AttribPtr[_TNL_ATTRIB_INDEX] = &tmp->Index;
}
- if (inputs & _TNL_BIT_EDGEFLAG) {
+ {
_tnl_import_edgeflag( ctx, GL_TRUE, sizeof(GLboolean) );
VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag;
}
/* These are constant & can be precalculated:
*/
- if (inputs & _TNL_BITS_MAT_ANY) {
- for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
- tmp->Attribs[i].count = 1;
- tmp->Attribs[i].data = (GLfloat (*)[4]) tnl->vtx.current[i];
- tmp->Attribs[i].start = tnl->vtx.current[i];
- tmp->Attribs[i].size = 4;
- tmp->Attribs[i].stride = 0;
- VB->AttribPtr[i] = &tmp->Attribs[i];
- }
- }
+ for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+ tmp->Attribs[i].count = 1;
+ tmp->Attribs[i].data = (GLfloat (*)[4]) tnl->vtx.current[i];
+ tmp->Attribs[i].start = tnl->vtx.current[i];
+ tmp->Attribs[i].size = 4;
+ tmp->Attribs[i].stride = 0;
+ VB->AttribPtr[i] = &tmp->Attribs[i];
+ }
/* Legacy pointers -- remove one day.
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
}
-
}
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables;
-
+
return GL_TRUE;
}
|| !tnl->AllowPixelFog;
}
- if (new_state & _NEW_ARRAY) {
- tnl->pipeline.run_input_changes |= ctx->Array.NewState; /* overkill */
- }
-
_ae_invalidate_state(ctx, new_state);
- tnl->pipeline.run_state_changes |= new_state;
- tnl->pipeline.build_state_changes |= (new_state &
- tnl->pipeline.build_state_trigger);
-
+ tnl->pipeline.new_state |= new_state;
tnl->vtx.eval.new_state |= new_state;
/* Calculate tnl->render_inputs:
/* Assume we haven't been getting state updates either:
*/
_tnl_InvalidateState( ctx, ~0 );
- tnl->pipeline.run_input_changes = ~0;
if (ctx->Light.ColorMaterialEnabled) {
_mesa_update_color_material( ctx,
#define MAX_PIPELINE_STAGES 30
-
/*
* Note: The first attributes match the VERT_ATTRIB_* definitions
* in mtypes.h. However, the tnl module has additional attributes
* for materials, color indexes, edge flags, etc.
*/
-/* Note: These are currently being used to define both inputs and
- * outputs from the tnl pipeline. A better solution (which would also
- * releive the congestion to slightly prolong the life of the bitmask
- * below) is to have the fixed function pipeline populate a set of
- * arrays named after those produced by the vertex program stage, and
- * have the rest the mesa backend work on those.
+/* Although it's nice to use these as bit indexes in a DWORD flag, we
+ * could manage without if necessary. Another limit currently is the
+ * number of bits allocated for these numbers in places like vertex
+ * program instruction formats and register layouts.
*/
enum {
_TNL_ATTRIB_POS = 0,
struct tnl_pipeline_stage
{
const char *name;
- GLuint check_state; /* All state referenced in check() --
- * When is the pipeline_stage struct
- * itself invalidated? Must be
- * constant.
- */
-
- /* Usually constant or set by the 'check' callback:
- */
- GLuint run_state; /* All state referenced in run() --
- * When is the cached output of the
- * stage invalidated?
- */
-
- GLboolean active; /* True if runnable in current state */
- GLuint inputs; /* VERT_* inputs to the stage */
- GLuint outputs; /* VERT_* outputs of the stage */
-
- /* Set in _tnl_run_pipeline():
- */
- GLuint changed_inputs; /* Generated value -- inputs to the
- * stage that have changed since last
- * call to 'run'.
- */
-
/* Private data for the pipeline stage:
*/
void *privatePtr;
- /* Free private data. May not be null.
+ /* Allocate private data
+ */
+ GLboolean (*create)( GLcontext *ctx, struct tnl_pipeline_stage * );
+
+ /* Free private data.
*/
void (*destroy)( struct tnl_pipeline_stage * );
- /* Called from _tnl_validate_pipeline(). Must update all fields in
- * the pipeline_stage struct for the current state.
+ /* Called on any statechange or input array size change or
+ * input array change to/from zero stride.
*/
- void (*check)( GLcontext *ctx, struct tnl_pipeline_stage * );
+ void (*validate)( GLcontext *ctx, struct tnl_pipeline_stage * );
/* Called from _tnl_run_pipeline(). The stage.changed_inputs value
* encodes all inputs to thee struct which have changed. If
GLboolean (*run)( GLcontext *ctx, struct tnl_pipeline_stage * );
};
+
+
/** Contains the array of all pipeline stages.
- * The default values are defined at the end of t_pipeline.c */
+ * The default values are defined at the end of t_pipeline.c
+ */
struct tnl_pipeline {
- GLuint build_state_trigger; /**< state changes which require build */
- GLuint build_state_changes; /**< state changes since last build */
- GLuint run_state_changes; /**< state changes since last run */
- GLuint run_input_changes; /**< VERT_* changes since last run */
- GLuint inputs; /**< VERT_* inputs to pipeline */
- /** This array has to end with a NULL-pointer. */
+
+ GLuint last_attrib_stride[_TNL_ATTRIB_MAX];
+ GLuint last_attrib_size[_TNL_ATTRIB_MAX];
+ GLuint input_changes;
+ GLuint new_state;
+
struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
GLuint nr_stages;
};
#include "t_context.h"
#include "t_pipeline.h"
-
+#include "t_vp_build.h"
void _tnl_install_pipeline( GLcontext *ctx,
const struct tnl_pipeline_stage **stages )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct tnl_pipeline *pipe = &tnl->pipeline;
GLuint i;
- ASSERT(pipe->nr_stages == 0);
-
- pipe->run_state_changes = ~0;
- pipe->run_input_changes = ~0;
- pipe->build_state_changes = ~0;
- pipe->build_state_trigger = 0;
- pipe->inputs = 0;
+ tnl->pipeline.new_state = ~0;
/* Create a writeable copy of each stage.
*/
for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) {
- MEMCPY( &pipe->stages[i], stages[i], sizeof( **stages ));
- pipe->build_state_trigger |= pipe->stages[i].check_state;
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ MEMCPY(s, stages[i], sizeof(*s));
+ if (s->create)
+ s->create(ctx, s);
}
- MEMSET( &pipe->stages[i], 0, sizeof( **stages ));
-
- pipe->nr_stages = i;
+ tnl->pipeline.nr_stages = i;
}
void _tnl_destroy_pipeline( GLcontext *ctx )
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
- for (i = 0 ; i < tnl->pipeline.nr_stages ; i++)
- tnl->pipeline.stages[i].destroy( &tnl->pipeline.stages[i] );
+ for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (s->destroy)
+ s->destroy(s);
+ }
tnl->pipeline.nr_stages = 0;
}
-/* TODO: merge validate with run.
- */
-void _tnl_validate_pipeline( GLcontext *ctx )
+
+
+static GLuint check_input_changes( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct tnl_pipeline *pipe = &tnl->pipeline;
- struct tnl_pipeline_stage *s = pipe->stages;
- GLuint newstate = pipe->build_state_changes;
- GLuint generated = 0;
- GLuint changed_inputs = 0;
-
- pipe->inputs = 0;
- pipe->build_state_changes = 0;
-
- for ( ; s->check ; s++) {
-
- s->changed_inputs |= s->inputs & changed_inputs;
-
- if (s->check_state & newstate) {
- if (s->active) {
- GLuint old_outputs = s->outputs;
- s->check(ctx, s);
- if (!s->active)
- changed_inputs |= old_outputs;
- }
- else
- s->check(ctx, s);
+ GLuint i;
+
+ for (i = 0; i < _TNL_ATTRIB_EDGEFLAG; i++) {
+ if (tnl->vb.AttribPtr[i]->size != tnl->pipeline.last_attrib_size[i] ||
+ tnl->vb.AttribPtr[i]->stride != tnl->pipeline.last_attrib_stride[i]) {
+ tnl->pipeline.last_attrib_size[i] = tnl->vb.AttribPtr[i]->size;
+ tnl->pipeline.last_attrib_stride[i] = tnl->vb.AttribPtr[i]->stride;
+ tnl->pipeline.input_changes |= 1<<i;
}
+ }
+
+ return tnl->pipeline.input_changes;
+}
+
- if (s->active) {
- pipe->inputs |= s->inputs & ~generated;
- generated |= s->outputs;
+static void check_output_changes( GLcontext *ctx )
+{
+#if 0
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ if (tnl->vb.ResultPtr[i]->size != tnl->last_result_size[i] ||
+ tnl->vb.ResultPtr[i]->stride != tnl->last_result_stride[i]) {
+ tnl->last_result_size[i] = tnl->vb.ResultPtr[i]->size;
+ tnl->last_result_stride[i] = tnl->vb.ResultPtr[i]->stride;
+ tnl->pipeline.output_changes |= 1<<i;
}
}
-}
+ if (tnl->pipeline.output_changes)
+ tnl->Driver.NotifyOutputChanges( ctx, tnl->pipeline.output_changes );
+#endif
+}
void _tnl_run_pipeline( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct tnl_pipeline *pipe = &tnl->pipeline;
- struct tnl_pipeline_stage *s = pipe->stages;
- GLuint changed_state = pipe->run_state_changes;
- GLuint changed_inputs = pipe->run_input_changes;
- GLboolean running = GL_TRUE;
-#ifdef HAVE_FAST_MATH
unsigned short __tmp;
-#endif
+ GLuint i;
if (!tnl->vb.Count)
return;
- pipe->run_state_changes = 0;
- pipe->run_input_changes = 0;
-
- /* Done elsewhere.
- */
- ASSERT(pipe->build_state_changes == 0);
-
-#ifdef HAVE_FAST_MATH
- START_FAST_MATH(__tmp);
-#endif
-
- /* If something changes in the pipeline, tag all subsequent stages
- * using this value for recalculation. Inactive stages have their
- * state and inputs examined to try to keep cached data alive over
- * state-changes.
+ /* Check for changed input sizes or change in stride to/from zero
+ * (ie const or non-const).
*/
- for ( ; s->run ; s++) {
- s->changed_inputs |= s->inputs & changed_inputs;
-
- if (s->run_state & changed_state)
- s->changed_inputs = s->inputs;
+ if (check_input_changes( ctx ) || tnl->pipeline.new_state) {
+ for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (s->validate)
+ s->validate( ctx, s );
+ }
+
+ tnl->pipeline.new_state = 0;
+ tnl->pipeline.input_changes = 0;
+ check_output_changes( ctx );
+ }
- if (s->active && running) {
- if (s->changed_inputs)
- changed_inputs |= s->outputs;
- running = s->run( ctx, s );
+ START_FAST_MATH(__tmp);
- s->changed_inputs = 0;
- }
+ for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (!s->run( ctx, s ))
+ break;
}
-#ifdef HAVE_FAST_MATH
END_FAST_MATH(__tmp);
-#endif
}
* case, if it becomes necessary to do so.
*/
const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
+#if TNL_FIXED_FUNCTION_PROGRAM
+ &_tnl_arb_vertex_program_stage,
+#else
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage,
&_tnl_point_attenuation_stage,
#if defined(FEATURE_NV_vertex_program) || defined(FEATURE_ARB_vertex_program)
&_tnl_vertex_program_stage,
+#endif
#endif
&_tnl_render_stage,
NULL
extern void _tnl_run_pipeline( GLcontext *ctx );
-extern void _tnl_validate_pipeline( GLcontext *ctx );
-
extern void _tnl_destroy_pipeline( GLcontext *ctx );
extern void _tnl_install_pipeline( GLcontext *ctx,
extern const struct tnl_pipeline_stage _tnl_texgen_stage;
extern const struct tnl_pipeline_stage _tnl_texture_transform_stage;
extern const struct tnl_pipeline_stage _tnl_point_attenuation_stage;
+extern const struct tnl_pipeline_stage _tnl_arb_vertex_program_stage;
extern const struct tnl_pipeline_stage _tnl_vertex_program_stage;
extern const struct tnl_pipeline_stage _tnl_render_stage;
return;
}
- if (tnl->pipeline.build_state_changes)
- _tnl_validate_pipeline( ctx );
-
_tnl_bind_vertex_list( ctx, node );
- /* Invalidate all stored data before and after run:
- */
- tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
tnl->Driver.RunPipeline( ctx );
- tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
}
/* Copy to current?
#include "math/m_translate.h"
#include "t_context.h"
#include "t_pipeline.h"
+#include "t_vp_build.h"
}
-#define RELADDR_MASK MAX_NV_VERTEX_PROGRAM_PARAMS
+#define RELADDR_MASK (MAX_NV_VERTEX_PROGRAM_PARAMS-1)
static void do_PRL( struct arb_vp_machine *m, union instruction op )
{
validate_vertex_program( GLcontext *ctx, struct tnl_pipeline_stage *stage )
{
struct arb_vp_machine *m = ARB_VP_MACHINE(stage);
- struct vertex_program *program = (ctx->VertexProgram._Enabled ?
- ctx->VertexProgram.Current :
- &ctx->_TnlProgram);
+ struct vertex_program *program =
+ (ctx->VertexProgram._Enabled ? ctx->VertexProgram.Current : 0);
- compile_vertex_program( m, program );
+#if TNL_FIXED_FUNCTION_PROGRAM
+ if (!program) {
+ _tnl_UpdateFixedFunctionProgram( ctx );
+ program = &ctx->_TnlProgram;
+ }
+#endif
- /* Grab the state GL state and put into registers:
- */
- m->File[PROGRAM_LOCAL_PARAM] = program->Base.LocalParams;
- m->File[PROGRAM_ENV_PARAM] = ctx->VertexProgram.Parameters;
- m->File[PROGRAM_STATE_VAR] = 0;
+ if (program) {
+ compile_vertex_program( m, program );
+
+ /* Grab the state GL state and put into registers:
+ */
+ m->File[PROGRAM_LOCAL_PARAM] = program->Base.LocalParams;
+ m->File[PROGRAM_ENV_PARAM] = ctx->VertexProgram.Parameters;
+ m->File[PROGRAM_STATE_VAR] = 0;
+ }
}
* Called the first time stage->run is called. In effect, don't
* allocate data until the first time the stage is run.
*/
-static void init_vertex_program( GLcontext *ctx,
- struct tnl_pipeline_stage *stage )
+static GLboolean init_vertex_program( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &(tnl->vb);
stage->privatePtr = MALLOC(sizeof(*m));
m = ARB_VP_MACHINE(stage);
if (!m)
- return;
+ return GL_FALSE;
/* arb_vertex_machine struct should subsume the VB:
*/
/* a few other misc allocations */
_mesa_vector4f_alloc( &m->ndcCoords, 0, size, 32 );
m->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
+
+
+#if TNL_FIXED_FUNCTION_PROGRAM
+ _mesa_allow_light_in_model( ctx, GL_FALSE );
+#endif
+
+
+ return GL_TRUE;
}
GLuint count = VB->Count;
GLuint i;
+ if (ctx->VertexProgram._Enabled ||
+ !ctx->Transform.CullVertexFlag)
+ return GL_TRUE;
+
VB->ClipOrMask &= ~CLIP_CULL_BIT;
VB->ClipAndMask |= CLIP_CULL_BIT;
}
-static void check_cull( GLcontext *ctx, struct tnl_pipeline_stage *stage )
-{
- stage->active = (!ctx->VertexProgram._Enabled &&
- ctx->Transform.CullVertexFlag);
-}
-
-
-static void dtr( struct tnl_pipeline_stage *stage )
-{
-}
-
const struct tnl_pipeline_stage _tnl_vertex_cull_stage =
{
"EXT_cull_vertex",
- _NEW_PROGRAM |
- _NEW_TRANSFORM,
- _NEW_TRANSFORM,
- GL_TRUE, /* active */
- _TNL_BIT_NORMAL |
- _TNL_BIT_POS, /* inputs */
- _TNL_BIT_POS, /* outputs */
- 0, /* changed_inputs */
NULL, /* private data */
- dtr, /* destructor */
- check_cull, /* check */
+ NULL, /* ctr */
+ NULL, /* destructor */
+ NULL,
run_cull_stage /* run -- initially set to init */
};
struct fog_stage_data *store = FOG_STAGE_DATA(stage);
GLvector4f *input;
- if (stage->changed_inputs == 0)
+ if (!ctx->Fog.Enabled || ctx->VertexProgram._Enabled)
return GL_TRUE;
+
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) {
/* Fog is computed from vertex or fragment Z values */
/* source = VB->ObjPtr or VB->EyePtr coords */
}
-static void
-check_fog_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
-{
- stage->active = ctx->Fog.Enabled && !ctx->VertexProgram._Enabled;
-
- if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
- stage->inputs = _TNL_BIT_POS;
- else
- stage->inputs = _TNL_BIT_FOG;
-}
-
/* Called the first time stage->run() is invoked.
*/
if (!inited)
init_static_data();
- /* Now run the stage.
- */
- stage->run = run_fog_stage;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
{
"build fog coordinates", /* name */
- _NEW_FOG|_NEW_PROGRAM, /* check_state */
- _NEW_FOG, /* run_state */
- GL_FALSE, /* active? */
- 0, /* inputs */
- _TNL_BIT_FOG, /* outputs */
- 0, /* changed_inputs */
NULL, /* private_data */
+ alloc_fog_data, /* dtr */
free_fog_data, /* dtr */
- check_fog_stage, /* check */
- alloc_fog_data /* run -- initially set to init. */
+ NULL, /* check */
+ run_fog_stage /* run -- initially set to init. */
};
#include "t_vb_lighttmp.h"
-static void init_lighting( void )
+static void init_lighting_tables( void )
{
static int done;
GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
GLuint idx;
+ if (!ctx->Light.Enabled || ctx->VertexProgram._Enabled)
+ return GL_TRUE;
+
/* Make sure we can talk about position x,y and z:
*/
- if (stage->changed_inputs & _TNL_BIT_POS) {
- if (input->size <= 2 && input == VB->ObjPtr) {
-
- _math_trans_4f( store->Input.data,
- VB->ObjPtr->data,
- VB->ObjPtr->stride,
- GL_FLOAT,
- VB->ObjPtr->size,
- 0,
- VB->Count );
-
- if (input->size <= 2) {
- /* Clean z.
- */
- _mesa_vector4f_clean_elem(&store->Input, VB->Count, 2);
- }
+ if (input->size <= 2 && input == VB->ObjPtr) {
+
+ _math_trans_4f( store->Input.data,
+ VB->ObjPtr->data,
+ VB->ObjPtr->stride,
+ GL_FLOAT,
+ VB->ObjPtr->size,
+ 0,
+ VB->Count );
+
+ if (input->size <= 2) {
+ /* Clean z.
+ */
+ _mesa_vector4f_clean_elem(&store->Input, VB->Count, 2);
+ }
- if (input->size <= 1) {
- /* Clean y.
- */
- _mesa_vector4f_clean_elem(&store->Input, VB->Count, 1);
- }
-
- input = &store->Input;
+ if (input->size <= 1) {
+ /* Clean y.
+ */
+ _mesa_vector4f_clean_elem(&store->Input, VB->Count, 1);
}
+
+ input = &store->Input;
}
idx = 0;
/* Called in place of do_lighting when the light table may have changed.
*/
-static GLboolean run_validate_lighting( GLcontext *ctx,
+static void validate_lighting( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
light_func *tab;
+ if (!ctx->Light.Enabled || ctx->VertexProgram._Enabled)
+ return;
+
if (ctx->Visual.rgbMode) {
if (ctx->Light._NeedVertices) {
if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
/* This and the above should only be done on _NEW_LIGHT:
*/
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
-
- /* Now run the stage...
- */
- stage->run = run_lighting;
- return stage->run( ctx, stage );
}
/* Called the first time stage->run is called. In effect, don't
* allocate data until the first time the stage is run.
*/
-static GLboolean run_init_lighting( GLcontext *ctx,
- struct tnl_pipeline_stage *stage )
+static GLboolean init_lighting( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct light_stage_data *store;
/* Do onetime init.
*/
- init_lighting();
+ init_lighting_tables();
_mesa_vector4f_alloc( &store->Input, 0, size, 32 );
_mesa_vector4f_alloc( &store->LitColor[0], 0, size, 32 );
store->LitIndex[1].size = 1;
store->LitIndex[1].stride = sizeof(GLfloat);
- /* Now validate the stage derived data...
- */
- stage->run = run_validate_lighting;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
-/*
- * Check if lighting is enabled. If so, configure the pipeline stage's
- * type, inputs, and outputs.
- */
-static void check_lighting( GLcontext *ctx, struct tnl_pipeline_stage *stage )
-{
- stage->active = ctx->Light.Enabled && !ctx->VertexProgram._Enabled;
- if (stage->active) {
- if (stage->privatePtr)
- stage->run = run_validate_lighting;
- stage->inputs = _TNL_BIT_NORMAL|_TNL_BITS_MAT_ANY;
- if (ctx->Light._NeedVertices)
- stage->inputs |= _TNL_BIT_POS;
- if (ctx->Light.ColorMaterialEnabled)
- stage->inputs |= _TNL_BIT_COLOR0;
-
- stage->outputs = _TNL_BIT_COLOR0;
- if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
- stage->outputs |= _TNL_BIT_COLOR1;
- }
-}
-
static void dtr( struct tnl_pipeline_stage *stage )
{
const struct tnl_pipeline_stage _tnl_lighting_stage =
{
"lighting", /* name */
- _NEW_LIGHT|_NEW_PROGRAM, /* recheck */
- _NEW_LIGHT|_NEW_MODELVIEW, /* recalc -- modelview dependency
- * otherwise not captured by inputs
- * (which may be _TNL_BIT_POS) */
- GL_FALSE, /* active? */
- 0, /* inputs */
- 0, /* outputs */
- 0, /* changed_inputs */
NULL, /* private_data */
+ init_lighting,
dtr, /* destroy */
- check_lighting, /* check */
- run_init_lighting /* run -- initially set to ctr */
+ validate_lighting,
+ run_lighting
};
sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
#endif
- /* Side-effects done, can we finish now?
- */
- if (stage->changed_inputs == 0)
- return;
store->LitColor[0].stride = 16;
store->LitColor[1].stride = 16;
sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
#endif
- if (stage->changed_inputs == 0)
- return;
-
store->LitColor[0].stride = 16;
store->LitColor[1].stride = 16;
VB->ColorPtr[1] = &store->LitColor[1];
#endif
- if (stage->changed_inputs == 0)
- return;
-
if (nr > 1) {
store->LitColor[0].stride = 16;
store->LitColor[1].stride = 16;
VB->ColorPtr[1] = &store->LitColor[1];
#endif
- if (stage->changed_inputs == 0)
- return;
-
if (nr > 1) {
store->LitColor[0].stride = 16;
store->LitColor[1].stride = 16;
VB->IndexPtr[1] = &store->LitIndex[1];
#endif
- if (stage->changed_inputs == 0)
- return;
-
indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data;
#if IDX & LIGHT_TWOSIDE
indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data;
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat *lengths;
- ASSERT(store->NormalTransform);
-
- if (stage->changed_inputs) {
- /* We can only use the display list's saved normal lengths if we've
- * got a transformation matrix with uniform scaling.
- */
- const GLfloat *lengths;
- if (ctx->ModelviewMatrixStack.Top->flags & MAT_FLAG_GENERAL_SCALE)
- lengths = NULL;
- else
- lengths = VB->NormalLengthPtr;
-
- store->NormalTransform( ctx->ModelviewMatrixStack.Top,
- ctx->_ModelViewInvScale,
- VB->NormalPtr, /* input normals */
- lengths,
- &store->normal ); /* resulting normals */
-
- if (VB->NormalPtr->count > 1) {
- store->normal.stride = 16;
- }
- else {
- store->normal.stride = 0;
- }
+ if (!store->NormalTransform)
+ return GL_TRUE;
+
+ /* We can only use the display list's saved normal lengths if we've
+ * got a transformation matrix with uniform scaling.
+ */
+ if (ctx->ModelviewMatrixStack.Top->flags & MAT_FLAG_GENERAL_SCALE)
+ lengths = NULL;
+ else
+ lengths = VB->NormalLengthPtr;
+
+ store->NormalTransform( ctx->ModelviewMatrixStack.Top,
+ ctx->_ModelViewInvScale,
+ VB->NormalPtr, /* input normals */
+ lengths,
+ &store->normal ); /* resulting normals */
+
+ if (VB->NormalPtr->count > 1) {
+ store->normal.stride = 16;
+ }
+ else {
+ store->normal.stride = 0;
}
VB->NormalPtr = &store->normal;
}
-static GLboolean run_validate_normal_stage( GLcontext *ctx,
+static void validate_normal_stage( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
-
+ if (ctx->VertexProgram._Enabled ||
+ (!ctx->Light.Enabled &&
+ !(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))) {
+ store->NormalTransform = NULL;
+ return;
+ }
+
+
if (ctx->_NeedEyeCoords) {
GLuint transform = NORM_TRANSFORM_NO_ROT;
store->NormalTransform = NULL;
}
}
-
- if (store->NormalTransform) {
- stage->run = run_normal_stage;
- return stage->run( ctx, stage );
- } else {
- stage->active = GL_FALSE; /* !!! */
- return GL_TRUE;
- }
}
-static void check_normal_transform( GLcontext *ctx,
- struct tnl_pipeline_stage *stage )
-{
- stage->active = !ctx->VertexProgram._Enabled &&
- (ctx->Light.Enabled || (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS));
-
- /* Don't clobber the initialize function:
- */
- if (stage->privatePtr)
- stage->run = run_validate_normal_stage;
-}
-
static GLboolean alloc_normal_data( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
return GL_FALSE;
_mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 );
-
- /* Now run the stage.
- */
- stage->run = run_validate_normal_stage;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
}
}
-#define _TNL_NEW_NORMAL_TRANSFORM (_NEW_MODELVIEW| \
- _NEW_TRANSFORM| \
- _NEW_PROGRAM| \
- _MESA_NEW_NEED_NORMALS| \
- _MESA_NEW_NEED_EYE_COORDS)
-
-
const struct tnl_pipeline_stage _tnl_normal_transform_stage =
{
"normal transform", /* name */
- _TNL_NEW_NORMAL_TRANSFORM, /* re-check */
- _TNL_NEW_NORMAL_TRANSFORM, /* re-run */
- GL_FALSE, /* active? */
- _TNL_BIT_NORMAL, /* inputs */
- _TNL_BIT_NORMAL, /* outputs */
- 0, /* changed_inputs */
NULL, /* private data */
+ alloc_normal_data,
free_normal_data, /* destructor */
- check_normal_transform, /* check */
- alloc_normal_data /* run -- initially set to alloc */
+ validate_normal_stage, /* check */
+ run_normal_stage
};
static GLboolean run_point_stage( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
- struct point_stage_data *store = POINT_STAGE_DATA(stage);
- struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
- const GLfloat (*eye)[4] = (const GLfloat (*)[4]) VB->EyePtr->data;
- const GLfloat p0 = ctx->Point.Params[0];
- const GLfloat p1 = ctx->Point.Params[1];
- const GLfloat p2 = ctx->Point.Params[2];
- const GLfloat pointSize = ctx->Point._Size;
- GLfloat (*size)[4] = store->PointSize.data;
- GLuint i;
-
- if (stage->changed_inputs) {
- /* XXX do threshold and min/max clamping here? */
+ if (ctx->Point._Attenuated && !ctx->VertexProgram._Enabled) {
+ struct point_stage_data *store = POINT_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat (*eye)[4] = (const GLfloat (*)[4]) VB->EyePtr->data;
+ const GLfloat p0 = ctx->Point.Params[0];
+ const GLfloat p1 = ctx->Point.Params[1];
+ const GLfloat p2 = ctx->Point.Params[2];
+ const GLfloat pointSize = ctx->Point._Size;
+ GLfloat (*size)[4] = store->PointSize.data;
+ GLuint i;
+
for (i = 0; i < VB->Count; i++) {
const GLfloat dist = -eye[i][2];
/* GLfloat dist = SQRTF(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]);*/
size[i][0] = pointSize / (p0 + dist * (p1 + dist * p2));
}
- }
- VB->PointSizePtr = &store->PointSize;
- VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->PointSize;
+ VB->PointSizePtr = &store->PointSize;
+ VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->PointSize;
+ }
return GL_TRUE;
}
-/* If point size attenuation is on we'll compute the point size for
- * each vertex in a special pipeline stage.
- */
-static void check_point_size( GLcontext *ctx, struct tnl_pipeline_stage *d )
-{
- d->active = ctx->Point._Attenuated && !ctx->VertexProgram._Enabled;
-}
static GLboolean alloc_point_data( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
return GL_FALSE;
_mesa_vector4f_alloc( &store->PointSize, 0, VB->Size, 32 );
-
- /* Now run the stage.
- */
- stage->run = run_point_stage;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
const struct tnl_pipeline_stage _tnl_point_attenuation_stage =
{
"point size attenuation", /* name */
- _NEW_POINT|_NEW_PROGRAM, /* check_state */
- _NEW_POINT, /* run_state */
- GL_FALSE, /* active */
- _TNL_BIT_POS, /* inputs */
- _TNL_BIT_POS, /* outputs */
- 0, /* changed_inputs (temporary value) */
NULL, /* stage private data */
+ alloc_point_data, /* alloc data */
free_point_data, /* destructor */
- check_point_size, /* check */
- alloc_point_data /* run -- initially set to alloc data */
+ NULL,
+ run_point_stage /* run */
};
#include "t_pipeline.h"
-/**
- * \warning These values _MUST_ match the values in the OutputRegisters[]
- * array in vpparse.c!!!
- */
-#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
-
/*!
* Private storage for the vertex program pipeline stage.
struct vertex_program *program = ctx->VertexProgram.Current;
GLuint i;
+ if (!ctx->VertexProgram._Enabled)
+ return GL_TRUE;
+
/* load program parameter registers (they're read-only) */
_mesa_init_vp_per_primitive_registers(ctx);
}
-/**
- * This function validates stuff.
- */
-static GLboolean run_validate_program( GLcontext *ctx,
- struct tnl_pipeline_stage *stage )
-{
-#if 000
- /* XXX do we need any validation for vertex programs? */
- GLuint ind = 0;
- light_func *tab;
-
- if (ctx->Visual.rgbMode) {
- if (ctx->Light._NeedVertices) {
- if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
- tab = _tnl_light_spec_tab;
- else
- tab = _tnl_light_tab;
- }
- else {
- if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
- tab = _tnl_light_fast_single_tab;
- else
- tab = _tnl_light_fast_tab;
- }
- }
- else
- tab = _tnl_light_ci_tab;
-
- if (ctx->Light.ColorMaterialEnabled)
- ind |= LIGHT_COLORMATERIAL;
-
- if (ctx->Light.Model.TwoSide)
- ind |= LIGHT_TWOSIDE;
-
- VP_STAGE_DATA(stage)->light_func_tab = &tab[ind];
-
- /* This and the above should only be done on _NEW_LIGHT:
- */
- _mesa_validate_all_lighting_tables( ctx );
-#endif
-
- /* Now run the stage...
- */
- stage->run = run_vp;
- return stage->run( ctx, stage );
-}
-
/**
* Called the first time stage->run is called. In effect, don't
* allocate data until the first time the stage is run.
*/
-static GLboolean run_init_vp( GLcontext *ctx,
- struct tnl_pipeline_stage *stage )
+static GLboolean init_vp( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &(tnl->vb);
_mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
- /* Now validate the stage derived data...
- */
- stage->run = run_validate_program;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
-/**
- * Check if vertex program mode is enabled.
- * If so, configure the pipeline stage's type, inputs, and outputs.
- */
-static void check_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
-{
- stage->active = ctx->VertexProgram._Enabled;
-
- if (stage->active) {
- /* Set stage->inputs equal to the bitmask of vertex attributes
- * which the program needs for inputs.
- */
- stage->inputs = ctx->VertexProgram.Current->InputsRead;
- }
-}
/**
GLuint i;
/* free the vertex program result arrays */
- for (i = 0; i < 15; i++)
+ for (i = 0; i < VERT_RESULT_MAX; i++)
_mesa_vector4f_free( &store->attribs[i] );
/* free misc arrays */
const struct tnl_pipeline_stage _tnl_vertex_program_stage =
{
"vertex-program",
- _NEW_ALL, /*XXX FIX */ /* recheck */
- _NEW_ALL, /*XXX FIX */ /* recalc */
- GL_FALSE, /* active */
- 0, /* inputs - calculated on the fly */
- _TNL_BITS_PROG_ANY, /* outputs -- could calculate */
- 0, /* changed_inputs */
NULL, /* private_data */
+ init_vp, /* create */
dtr, /* destroy */
- check_vp, /* check */
- run_init_vp /* run -- initially set to ctr */
+ NULL, /* validate */
+ run_vp /* run -- initially set to ctr */
};
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint new_inputs = stage->changed_inputs;
tnl_render_func *tab;
GLint pass = 0;
ASSERT(tnl->Driver.Render.ClippedPolygon);
ASSERT(tnl->Driver.Render.Finish);
- tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, new_inputs );
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
if (VB->ClipOrMask) {
tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
-/* Quite a bit of work involved in finding out the inputs for the
- * render stage.
- */
-static void check_render( GLcontext *ctx, struct tnl_pipeline_stage *stage )
-{
- stage->inputs = TNL_CONTEXT(ctx)->render_inputs;
-}
-
-
-
-
-static void dtr( struct tnl_pipeline_stage *stage )
-{
- (void) stage;
-}
const struct tnl_pipeline_stage _tnl_render_stage =
{
"render", /* name */
- (_NEW_BUFFERS |
- _DD_NEW_SEPARATE_SPECULAR |
- _DD_NEW_FLATSHADE |
- _NEW_TEXTURE|
- _NEW_LIGHT|
- _NEW_POINT|
- _NEW_FOG|
- _DD_NEW_TRI_UNFILLED |
- _NEW_RENDERMODE), /* re-check (new inputs, interp function) */
- 0, /* re-run (always runs) */
- GL_TRUE, /* active? */
- 0, /* inputs (set in check_render) */
- 0, /* outputs */
- 0, /* changed_inputs */
NULL, /* private data */
- dtr, /* destructor */
- check_render, /* check */
+ NULL, /* creator */
+ NULL, /* destructor */
+ NULL, /* validate */
run_render /* run */
};
+
static GLboolean run_texgen_stage( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
- struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage );
+ struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
GLuint i;
- for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
- if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) {
- if (stage->changed_inputs & (_TNL_BIT_POS | _TNL_BIT_NORMAL | _TNL_BIT_TEX(i)))
- store->TexgenFunc[i]( ctx, store, i );
+ if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Enabled)
+ return GL_TRUE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+
+ if (texUnit->TexGenEnabled) {
+
+ store->TexgenFunc[i]( ctx, store, i );
VB->AttribPtr[VERT_ATTRIB_TEX0+i] =
VB->TexCoordPtr[i] = &store->texcoord[i];
}
+ }
return GL_TRUE;
}
-
-
-static GLboolean run_validate_texgen_stage( GLcontext *ctx,
- struct tnl_pipeline_stage *stage )
+static void validate_texgen_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
{
struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
GLuint i;
+ if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Enabled)
+ return;
+
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
}
}
}
-
- stage->run = run_texgen_stage;
- return stage->run( ctx, stage );
}
-static void check_texgen( GLcontext *ctx, struct tnl_pipeline_stage *stage )
-{
- GLuint i;
- stage->active = 0;
-
- if (ctx->Texture._TexGenEnabled && !ctx->VertexProgram._Enabled) {
- GLuint inputs = 0;
- GLuint outputs = 0;
-
- if (ctx->Texture._GenFlags & (TEXGEN_OBJ_LINEAR | TEXGEN_NEED_EYE_COORD))
- inputs |= _TNL_BIT_POS;
-
- if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
- inputs |= _TNL_BIT_NORMAL;
-
- for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
- if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i))
- {
- outputs |= _TNL_BIT_TEX(i);
-
- /* Need the original input in case it contains a Q coord:
- * (sigh)
- */
- inputs |= _TNL_BIT_TEX(i);
-
- /* Something for Feedback? */
- }
-
- if (stage->privatePtr)
- stage->run = run_validate_texgen_stage;
- stage->active = 1;
- stage->inputs = inputs;
- stage->outputs = outputs;
- }
-}
-
store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3);
store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat));
- /* Now validate and run the stage.
- */
- stage->run = run_validate_texgen_stage;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
const struct tnl_pipeline_stage _tnl_texgen_stage =
{
"texgen", /* name */
- _NEW_TEXTURE|_NEW_PROGRAM, /* when to call check() */
- _NEW_TEXTURE, /* when to invalidate stored data */
- GL_FALSE, /* active? */
- 0, /* inputs */
- 0, /* outputs */
- 0, /* changed_inputs */
NULL, /* private data */
+ alloc_texgen_data, /* destructor */
free_texgen_data, /* destructor */
- check_texgen, /* check */
- alloc_texgen_data /* run -- initially set to alloc data */
+ validate_texgen_stage, /* check */
+ run_texgen_stage /* run -- initially set to alloc data */
};
#define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr)
-static void check_texmat( GLcontext *ctx, struct tnl_pipeline_stage *stage )
-{
- GLuint i;
- stage->active = 0;
-
- if (ctx->Texture._TexMatEnabled && !ctx->VertexProgram._Enabled) {
- GLuint flags = 0;
- for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
- if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
- flags |= _TNL_BIT_TEX(i);
-
- stage->active = 1;
- stage->inputs = flags;
- stage->outputs = flags;
- }
-}
static GLboolean run_texmat_stage( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint i;
+ if (!ctx->Texture._TexMatEnabled || ctx->VertexProgram._Enabled)
+ return GL_TRUE;
+
/* ENABLE_TEXMAT implies that the texture matrix is not the
* identity, so we don't have to check that here.
*/
- for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) {
- if (stage->changed_inputs & _TNL_BIT_TEX(i))
- (void) TransformRaw( &store->texcoord[i],
- ctx->TextureMatrixStack[i].Top,
- VB->TexCoordPtr[i]);
+ (void) TransformRaw( &store->texcoord[i],
+ ctx->TextureMatrixStack[i].Top,
+ VB->TexCoordPtr[i]);
VB->AttribPtr[VERT_ATTRIB_TEX0+i] =
VB->TexCoordPtr[i] = &store->texcoord[i];
}
+ }
+
return GL_TRUE;
}
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
_mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
- /* Now run the stage.
- */
- stage->run = run_texmat_stage;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
const struct tnl_pipeline_stage _tnl_texture_transform_stage =
{
"texture transform", /* name */
- _NEW_TEXTURE|_NEW_TEXTURE_MATRIX|_NEW_PROGRAM, /* check_state */
- _NEW_TEXTURE|_NEW_TEXTURE_MATRIX, /* run_state */
- GL_FALSE, /* active? */
- 0, /* inputs */
- 0, /* outputs */
- 0, /* changed_inputs */
NULL, /* private data */
+ alloc_texmat_data,
free_texmat_data, /* destructor */
- check_texmat, /* check */
- alloc_texmat_data, /* run -- initially set to init */
+ NULL,
+ run_texmat_stage,
};
GLubyte *clipmask;
GLubyte ormask;
GLubyte andmask;
-
-
- /* Need these because it's difficult to replay the sideeffects
- * analytically.
- */
- GLvector4f *save_eyeptr;
- GLvector4f *save_clipptr;
- GLvector4f *save_ndcptr;
};
#define VERTEX_STAGE_DATA(stage) ((struct vertex_stage_data *)stage->privatePtr)
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- ASSERT(!ctx->VertexProgram._Enabled);
-
- if (stage->changed_inputs) {
-
- if (ctx->_NeedEyeCoords) {
- /* Separate modelview transformation:
- * Use combined ModelProject to avoid some depth artifacts
- */
- if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY)
- VB->EyePtr = VB->ObjPtr;
- else
- VB->EyePtr = TransformRaw( &store->eye,
- ctx->ModelviewMatrixStack.Top,
- VB->ObjPtr);
-#if 0
- /* examine some eye coordinates */
- {
- GLuint i;
- GLfloat *v = VB->EyePtr->start;
- for (i = 0; i < 4; i++) {
- _mesa_printf("eye[%d] = %g, %g, %g, %g\n",
- i, v[0], v[1], v[2], v[3]);
- v += 4;
- }
- }
-#endif
- }
-
- VB->ClipPtr = TransformRaw( &store->clip,
- &ctx->_ModelProjectMatrix,
- VB->ObjPtr );
-
- /* Drivers expect this to be clean to element 4...
- */
- switch (VB->ClipPtr->size) {
- case 1:
- /* impossible */
- case 2:
- _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
- /* fall-through */
- case 3:
- _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
- /* fall-through */
- case 4:
- break;
- }
-
-#if 0
- /* examine some clip coordinates */
- {
- GLuint i;
- GLfloat *v = VB->ClipPtr->start;
- for (i = 0; i < 4; i++) {
- _mesa_printf("clip[%d] = %g, %g, %g, %g\n",
- i, v[0], v[1], v[2], v[3]);
- v += 4;
- }
- }
-#endif
-
- /* Cliptest and perspective divide. Clip functions must clear
- * the clipmask.
+ if (ctx->VertexProgram._Enabled)
+ return GL_TRUE;
+
+ if (ctx->_NeedEyeCoords) {
+ /* Separate modelview transformation:
+ * Use combined ModelProject to avoid some depth artifacts
*/
- store->ormask = 0;
- store->andmask = CLIP_ALL_BITS;
-
- if (tnl->NeedNdcCoords) {
- VB->NdcPtr =
- _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
- &store->proj,
- store->clipmask,
- &store->ormask,
- &store->andmask );
- }
- else {
- VB->NdcPtr = NULL;
- _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
- NULL,
- store->clipmask,
- &store->ormask,
- &store->andmask );
- }
+ if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY)
+ VB->EyePtr = VB->ObjPtr;
+ else
+ VB->EyePtr = TransformRaw( &store->eye,
+ ctx->ModelviewMatrixStack.Top,
+ VB->ObjPtr);
+ }
- if (store->andmask)
- return GL_FALSE;
+ VB->ClipPtr = TransformRaw( &store->clip,
+ &ctx->_ModelProjectMatrix,
+ VB->ObjPtr );
+ /* Drivers expect this to be clean to element 4...
+ */
+ switch (VB->ClipPtr->size) {
+ case 1:
+ /* impossible */
+ case 2:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+ /* fall-through */
+ case 3:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+ /* fall-through */
+ case 4:
+ break;
+ }
- /* Test userclip planes. This contributes to VB->ClipMask, so
- * is essentially required to be in this stage.
- */
- if (ctx->Transform.ClipPlanesEnabled) {
- usercliptab[VB->ClipPtr->size]( ctx,
- VB->ClipPtr,
- store->clipmask,
- &store->ormask,
- &store->andmask );
-
- if (store->andmask)
- return GL_FALSE;
- }
-
- VB->ClipAndMask = store->andmask;
- VB->ClipOrMask = store->ormask;
- VB->ClipMask = store->clipmask;
-
- store->save_eyeptr = VB->EyePtr;
- store->save_clipptr = VB->ClipPtr;
- store->save_ndcptr = VB->NdcPtr;
+
+ /* Cliptest and perspective divide. Clip functions must clear
+ * the clipmask.
+ */
+ store->ormask = 0;
+ store->andmask = CLIP_ALL_BITS;
+
+ if (tnl->NeedNdcCoords) {
+ VB->NdcPtr =
+ _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ &store->proj,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
}
else {
- /* Replay the sideeffects.
- */
- VB->EyePtr = store->save_eyeptr;
- VB->ClipPtr = store->save_clipptr;
- VB->NdcPtr = store->save_ndcptr;
- VB->ClipMask = store->clipmask;
- VB->ClipAndMask = store->andmask;
- VB->ClipOrMask = store->ormask;
+ VB->NdcPtr = NULL;
+ _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ NULL,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+ }
+
+ if (store->andmask)
+ return GL_FALSE;
+
+
+ /* Test userclip planes. This contributes to VB->ClipMask, so
+ * is essentially required to be in this stage.
+ */
+ if (ctx->Transform.ClipPlanesEnabled) {
+ usercliptab[VB->ClipPtr->size]( ctx,
+ VB->ClipPtr,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+
if (store->andmask)
return GL_FALSE;
}
+ VB->ClipAndMask = store->andmask;
+ VB->ClipOrMask = store->ormask;
+ VB->ClipMask = store->clipmask;
+
return GL_TRUE;
}
-static void check_vertex( GLcontext *ctx, struct tnl_pipeline_stage *stage )
-{
- stage->active = !ctx->VertexProgram._Enabled;
-}
-
static GLboolean init_vertex_stage( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
!store->proj.data)
return GL_FALSE;
- /* Now run the stage.
- */
- stage->run = run_vertex_stage;
- return stage->run( ctx, stage );
+ return GL_TRUE;
}
static void dtr( struct tnl_pipeline_stage *stage )
const struct tnl_pipeline_stage _tnl_vertex_transform_stage =
{
"modelview/project/cliptest/divide",
- _NEW_PROGRAM, /* check_state: only care about vertex prog */
- _MESA_NEW_NEED_EYE_COORDS | /* run_state: when to invalidate / re-run */
- _NEW_MODELVIEW|
- _NEW_PROJECTION|
- _NEW_PROGRAM|
- _NEW_TRANSFORM,
- GL_TRUE, /* active */
- _TNL_BIT_POS, /* inputs */
- _TNL_BIT_POS, /* outputs */
- 0, /* changed_inputs */
NULL, /* private data */
+ init_vertex_stage,
dtr, /* destructor */
- check_vertex, /* check */
- init_vertex_stage /* run -- initially set to init */
+ NULL,
+ run_vertex_stage /* run -- initially set to init */
};
* generated program with line/function references for each
* instruction back into this file:
*/
-#define DISASSEM 1
+#define DISASSEM 0
/* Use uregs to represent registers internally, translate to Mesa's
* expected formats on emit.
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 2005 Tungsten Graphics All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _T_ARB_BUILD_H
+#define _T_ARB_BUILD_H
+
+#include "mtypes.h"
+
+/* Define to 1 to test fixed-function execution via vertex programs:
+ */
+#define TNL_FIXED_FUNCTION_PROGRAM 0
+
+extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx );
+
+#endif
if (ctx->NewState)
_mesa_update_state( ctx );
- if (tnl->pipeline.build_state_changes)
- _tnl_validate_pipeline( ctx );
-
_tnl_vb_bind_vtx( ctx );
- /* Invalidate all stored data before and after run:
- */
- tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
tnl->Driver.RunPipeline( ctx );
- tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
}
}