Simplify the pipeline_stage structure

- 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.
This commit is contained in:
Keith Whitwell 2005-04-22 12:51:19 +00:00
parent 6a13c7da4c
commit 6f973f3367
24 changed files with 422 additions and 835 deletions

View File

@ -2649,6 +2649,9 @@ struct __GLcontextRec
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 */

View File

@ -118,16 +118,18 @@ TNL_SOURCES = \
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 \
@ -137,6 +139,8 @@ TNL_SOURCES = \
tnl/t_vtx_eval.c \
tnl/t_vtx_exec.c
SHADER_SOURCES = \
shader/arbfragparse.c \
shader/arbprogparse.c \

View File

@ -91,9 +91,6 @@ static void _tnl_draw_range_elements( GLcontext *ctx, GLenum mode,
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;
@ -104,20 +101,7 @@ static void _tnl_draw_range_elements( GLcontext *ctx, GLenum mode,
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 );
}
@ -131,7 +115,6 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count)
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);
@ -141,9 +124,6 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei 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) {
@ -266,16 +246,7 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count)
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;
}
}
}

View File

@ -244,7 +244,6 @@ void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLint end)
{
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;
@ -269,77 +268,61 @@ void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLint end)
}
/* 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.
@ -357,5 +340,4 @@ void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLint end)
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
}
}

View File

@ -124,7 +124,7 @@ _tnl_CreateContext( GLcontext *ctx )
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;
}
@ -156,16 +156,9 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
|| !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:
@ -217,7 +210,6 @@ _tnl_wakeup_exec( GLcontext *ctx )
/* 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,

View File

@ -82,18 +82,15 @@
#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,
@ -463,43 +460,23 @@ struct vertex_buffer
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
@ -512,15 +489,18 @@ struct tnl_pipeline_stage
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;
};

View File

@ -37,33 +37,26 @@
#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 )
@ -71,100 +64,89 @@ 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);
}
if (s->active) {
pipe->inputs |= s->inputs & ~generated;
generated |= s->outputs;
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;
}
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.
/* Check for changed input sizes or change in stride to/from zero
* (ie const or non-const).
*/
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.
*/
for ( ; s->run ; s++) {
s->changed_inputs |= s->inputs & changed_inputs;
if (s->run_state & changed_state)
s->changed_inputs = s->inputs;
if (s->active && running) {
if (s->changed_inputs)
changed_inputs |= s->outputs;
running = s->run( ctx, s );
s->changed_inputs = 0;
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 );
}
START_FAST_MATH(__tmp);
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
}
@ -201,6 +183,9 @@ void _tnl_run_pipeline( GLcontext *ctx )
* 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,
@ -210,6 +195,7 @@ const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
&_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

View File

@ -36,8 +36,6 @@
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,
@ -54,6 +52,7 @@ extern const struct tnl_pipeline_stage _tnl_fog_coordinate_stage;
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;

View File

@ -204,16 +204,9 @@ void _tnl_playback_vertex_list( GLcontext *ctx, void *data )
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?

View File

@ -40,6 +40,7 @@
#include "math/m_translate.h"
#include "t_context.h"
#include "t_pipeline.h"
#include "t_vp_build.h"
@ -416,7 +417,7 @@ static void do_PAR( struct arb_vp_machine *m, union instruction op )
}
#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 )
{
@ -1458,17 +1459,25 @@ static void
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;
}
}
@ -1481,8 +1490,8 @@ validate_vertex_program( GLcontext *ctx, struct tnl_pipeline_stage *stage )
* 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);
@ -1493,7 +1502,7 @@ static void init_vertex_program( GLcontext *ctx,
stage->privatePtr = MALLOC(sizeof(*m));
m = ARB_VP_MACHINE(stage);
if (!m)
return;
return GL_FALSE;
/* arb_vertex_machine struct should subsume the VB:
*/
@ -1509,6 +1518,14 @@ static void init_vertex_program( GLcontext *ctx,
/* 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;
}

View File

@ -57,6 +57,10 @@ static GLboolean run_cull_stage( GLcontext *ctx,
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;
@ -81,31 +85,13 @@ static GLboolean run_cull_stage( GLcontext *ctx,
}
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 */
};

View File

@ -148,9 +148,10 @@ run_fog_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
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 */
@ -213,17 +214,6 @@ run_fog_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
}
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.
*/
@ -243,10 +233,7 @@ alloc_fog_data(GLcontext *ctx, struct tnl_pipeline_stage *stage)
if (!inited)
init_static_data();
/* Now run the stage.
*/
stage->run = run_fog_stage;
return stage->run( ctx, stage );
return GL_TRUE;
}
@ -265,14 +252,9 @@ free_fog_data(struct tnl_pipeline_stage *stage)
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. */
};

View File

@ -180,7 +180,7 @@ static light_func _tnl_light_ci_tab[MAX_LIGHT_FUNC];
#include "t_vb_lighttmp.h"
static void init_lighting( void )
static void init_lighting_tables( void )
{
static int done;
@ -203,33 +203,34 @@ static GLboolean run_lighting( GLcontext *ctx,
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) {
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 );
_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 <= 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;
}
idx = 0;
@ -255,11 +256,14 @@ static GLboolean run_lighting( GLcontext *ctx,
/* 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)
@ -283,11 +287,6 @@ static GLboolean run_validate_lighting( GLcontext *ctx,
/* 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 );
}
@ -295,8 +294,8 @@ static GLboolean run_validate_lighting( GLcontext *ctx,
/* 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;
@ -309,7 +308,7 @@ static GLboolean run_init_lighting( GLcontext *ctx,
/* 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 );
@ -329,36 +328,11 @@ static GLboolean run_init_lighting( GLcontext *ctx,
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 )
{
@ -380,16 +354,9 @@ 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
};

View File

@ -82,10 +82,6 @@ static void TAG(light_rgba_spec)( GLcontext *ctx,
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;
@ -271,9 +267,6 @@ static void TAG(light_rgba)( GLcontext *ctx,
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;
@ -461,9 +454,6 @@ static void TAG(light_fast_rgba_single)( GLcontext *ctx,
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;
@ -574,9 +564,6 @@ static void TAG(light_fast_rgba)( GLcontext *ctx,
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;
@ -683,9 +670,6 @@ static void TAG(light_ci)( GLcontext *ctx,
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;

View File

@ -55,31 +55,30 @@ static GLboolean run_normal_stage( GLcontext *ctx,
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
const GLfloat *lengths;
ASSERT(store->NormalTransform);
if (!store->NormalTransform)
return GL_TRUE;
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;
/* 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 */
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 (VB->NormalPtr->count > 1) {
store->normal.stride = 16;
}
else {
store->normal.stride = 0;
}
VB->NormalPtr = &store->normal;
@ -90,12 +89,19 @@ static GLboolean run_normal_stage( GLcontext *ctx,
}
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;
@ -129,29 +135,9 @@ static GLboolean run_validate_normal_stage( GLcontext *ctx,
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 )
@ -164,11 +150,7 @@ static GLboolean alloc_normal_data( GLcontext *ctx,
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;
}
@ -183,25 +165,13 @@ static void free_normal_data( struct tnl_pipeline_stage *stage )
}
}
#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
};

View File

@ -44,39 +44,31 @@ struct point_stage_data {
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 (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;
if (stage->changed_inputs) {
/* XXX do threshold and min/max clamping here? */
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 )
@ -89,11 +81,7 @@ static GLboolean alloc_point_data( GLcontext *ctx,
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;
}
@ -110,14 +98,9 @@ static void free_point_data( struct tnl_pipeline_stage *stage )
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 */
};

View File

@ -51,26 +51,6 @@
#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.
@ -100,6 +80,9 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *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);
@ -223,61 +206,14 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
}
/**
* 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);
@ -300,29 +236,11 @@ static GLboolean run_init_vp( GLcontext *ctx,
_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;
}
}
/**
@ -336,7 +254,7 @@ static void dtr( struct tnl_pipeline_stage *stage )
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 */
@ -354,14 +272,9 @@ static void dtr( struct tnl_pipeline_stage *stage )
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 */
};

View File

@ -268,7 +268,6 @@ static GLboolean run_render( GLcontext *ctx,
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint new_inputs = stage->changed_inputs;
tnl_render_func *tab;
GLint pass = 0;
@ -293,7 +292,7 @@ static GLboolean run_render( GLcontext *ctx,
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;
@ -340,42 +339,14 @@ static GLboolean run_render( GLcontext *ctx,
/* 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 */
};

View File

@ -480,34 +480,42 @@ static void texgen( GLcontext *ctx,
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];
@ -541,48 +549,9 @@ static GLboolean run_validate_texgen_stage( GLcontext *ctx,
}
}
}
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;
}
}
@ -606,10 +575,7 @@ static GLboolean alloc_texgen_data( GLcontext *ctx,
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;
}
@ -637,14 +603,9 @@ static void free_texgen_data( struct tnl_pipeline_stage *stage )
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 */
};

View File

@ -52,23 +52,7 @@ struct texmat_stage_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 )
@ -77,19 +61,23 @@ static GLboolean run_texmat_stage( GLcontext *ctx,
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;
}
@ -111,10 +99,7 @@ static GLboolean alloc_texmat_data( GLcontext *ctx,
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;
}
@ -137,14 +122,9 @@ static void free_texmat_data( struct tnl_pipeline_stage *stage )
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,
};

View File

@ -47,14 +47,6 @@ struct vertex_stage_data {
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)
@ -134,137 +126,90 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
ASSERT(!ctx->VertexProgram._Enabled);
if (ctx->VertexProgram._Enabled)
return GL_TRUE;
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...
if (ctx->_NeedEyeCoords) {
/* Separate modelview transformation:
* Use combined ModelProject to avoid some depth artifacts
*/
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 (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 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
VB->ClipPtr = TransformRaw( &store->clip,
&ctx->_ModelProjectMatrix,
VB->ObjPtr );
/* 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 {
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;
/* 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 );
/* Cliptest and perspective divide. Clip functions must clear
* the clipmask.
*/
store->ormask = 0;
store->andmask = CLIP_ALL_BITS;
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;
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 )
{
@ -289,10 +234,7 @@ static GLboolean init_vertex_stage( GLcontext *ctx,
!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 )
@ -314,18 +256,9 @@ 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 */
};

View File

@ -46,7 +46,7 @@
* 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.

37
src/mesa/tnl/t_vp_build.h Normal file
View File

@ -0,0 +1,37 @@
/*
* 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

View File

@ -272,16 +272,9 @@ void _tnl_flush_vtx( GLcontext *ctx )
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;
}
}