summaryrefslogtreecommitdiffstats
path: root/src/mesa/tnl
diff options
context:
space:
mode:
authorKeith Whitwell <[email protected]>2000-11-16 21:05:34 +0000
committerKeith Whitwell <[email protected]>2000-11-16 21:05:34 +0000
commit23caf20169ac38436ee9c13914f1d6aa7cf6bb5e (patch)
tree21307f7bbcaf9ee1e841d7e7bee130570a7b5b95 /src/mesa/tnl
parent179516673211a2350e479d5321840291f339f5dd (diff)
Move the transform and lighting code to two new directories
math: Provides basic matrix and vector functionality that might be useful to multiple software t&l implementations, and is used by core mesa to manage the Model, Project, etc matrices. tnl: The real transform & lighting code from core mesa, including everything from glVertex3f through vertex buffer handling, transformation, clipping, lighting and handoff to a driver for rasterization. The interfaces of these can be further tightened up, but the basic splitting up of state and code move is done.
Diffstat (limited to 'src/mesa/tnl')
-rw-r--r--src/mesa/tnl/t_context.c201
-rw-r--r--src/mesa/tnl/t_context.h629
-rw-r--r--src/mesa/tnl/t_pipeline.c496
-rw-r--r--src/mesa/tnl/t_pipeline.h59
-rw-r--r--src/mesa/tnl/tnl.h48
5 files changed, 1433 insertions, 0 deletions
diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c
new file mode 100644
index 00000000000..bab6326ebaf
--- /dev/null
+++ b/src/mesa/tnl/t_context.c
@@ -0,0 +1,201 @@
+#include "types.h"
+#include "mem.h"
+
+#include "t_context.h"
+#include "t_clip.h"
+#include "t_cva.h"
+#include "t_dlist.h"
+#include "t_eval.h"
+#include "t_pipeline.h"
+#include "t_shade.h"
+#include "t_light.h"
+#include "t_texture.h"
+#include "t_stages.h"
+#include "t_varray.h"
+#include "t_vb.h"
+#include "t_vbrender.h"
+#include "t_vbxform.h"
+#include "tnl.h"
+
+#if !defined(THREADS)
+struct immediate *_mesa_CurrentInput = NULL;
+#endif
+
+
+GLboolean
+_tnl_flush_vertices( GLcontext *ctx, GLuint flush_flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+
+ if ((IM->Flag[IM->Count] & (VERT_BEGIN|VERT_END)) != VERT_END ||
+ (flush_flags & (FLUSH_STORED_VERTICES|FLUSH_UPDATE_CURRENT)))
+ {
+ if (IM->Flag[IM->Start])
+ _mesa_flush_vb( ctx );
+
+ /* Although this code updates the ctx->Current values, that bit
+ * is left set as there is no easy mechanism to set it
+ * elsewhere. This means that each time core wants to examine
+ * ctx->Current, this function will be called. After the first
+ * time, however, it will be a no-op.
+ */
+ ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES |
+ FLUSH_INSIDE_BEGIN_END);
+
+ return (tnl->_CurrentPrimitive == GL_POLYGON+1);
+ }
+ else
+ return GL_TRUE;
+}
+
+
+GLboolean
+_tnl_CreateContext( GLcontext *ctx )
+{
+ TNLcontext *tnl;
+ static int firsttime = 1;
+
+ /* Onetime initializations. Doesn't really matter if this gets
+ * done twice: no need for mutexes.
+ */
+ if (firsttime) {
+ firsttime = 0;
+ _tnl_clip_init( );
+ _tnl_eval_init( );
+ _tnl_shade_init( );
+ _tnl_texture_init( );
+ _tnl_trans_elt_init( );
+ _tnl_vbrender_init( );
+ _tnl_stages_init( );
+ }
+
+ /* Create the TNLcontext structure
+ */
+ ctx->swtnl_context = tnl = CALLOC( sizeof(TNLcontext) );
+ if (!tnl) {
+ return GL_FALSE;
+ }
+
+ /* Create and hook in the data structures available from ctx.
+ */
+ ctx->swtnl_vb = (void *)gl_vb_create_for_immediate( ctx );
+ if (!ctx->swtnl_vb) {
+ FREE(tnl);
+ ctx->swtnl_context = 0;
+ return GL_FALSE;
+ }
+
+ ctx->swtnl_im = (void *)TNL_VB(ctx)->IM;
+
+
+ /* Initialize tnl state.
+ */
+ _tnl_dlist_init( ctx );
+ _tnl_pipeline_init( ctx );
+
+ tnl->_CurrentFlag = (VERT_NORM |
+ VERT_INDEX |
+ VERT_RGBA |
+ VERT_SPEC_RGB |
+ VERT_FOG_COORD |
+ VERT_EDGE |
+ VERT_TEX0_12 |
+ VERT_TEX1_12 |
+ VERT_TEX2_12 |
+ VERT_TEX3_12 |
+ VERT_MATERIAL);
+
+ tnl->_CurrentPrimitive = GL_POLYGON+1;
+
+ gl_reset_vb( TNL_VB(ctx) );
+ gl_reset_input( ctx );
+
+
+ /* Set a few default values in the driver struct. This is a
+ * temporary mechanism.
+ */
+ ctx->Driver.RenderVBCulledTab = _tnl_render_tab_cull;
+ ctx->Driver.RenderVBClippedTab = _tnl_render_tab_clipped;
+ ctx->Driver.RenderVBRawTab = _tnl_render_tab_raw;
+ ctx->Driver.NewList = _tnl_NewList;
+ ctx->Driver.EndList = _tnl_EndList;
+ ctx->Driver.FlushVertices = _tnl_flush_vertices;
+ ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT;
+ ctx->Driver.LightingSpaceChange = _tnl_LightingSpaceChange;
+ ctx->Driver.MakeCurrent = _tnl_MakeCurrent;
+ ctx->Driver.VertexPointer = _tnl_VertexPointer;
+ ctx->Driver.NormalPointer = _tnl_NormalPointer;
+ ctx->Driver.ColorPointer = _tnl_ColorPointer;
+ ctx->Driver.FogCoordPointer = _tnl_FogCoordPointer;
+ ctx->Driver.IndexPointer = _tnl_IndexPointer;
+ ctx->Driver.SecondaryColorPointer = _tnl_SecondaryColorPointer;
+ ctx->Driver.TexCoordPointer = _tnl_TexCoordPointer;
+ ctx->Driver.EdgeFlagPointer = _tnl_EdgeFlagPointer;
+
+ return GL_TRUE;
+}
+
+
+void
+_tnl_DestroyContext( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ if (TNL_CURRENT_IM(ctx) != TNL_VB(ctx)->IM)
+ gl_immediate_free( TNL_CURRENT_IM(ctx) );
+
+ gl_vb_free( TNL_VB(ctx) );
+
+ /* Free cache of immediate buffers. */
+ while (tnl->nr_im_queued-- > 0) {
+ struct immediate * next = tnl->freed_im_queue->next;
+ ALIGN_FREE( tnl->freed_im_queue );
+ tnl->freed_im_queue = next;
+ }
+}
+
+
+/* Update all state that references _NeedEyeCoords
+ */
+void
+_tnl_LightingSpaceChange( GLcontext *ctx )
+{
+ _tnl_update_normal_transform( ctx );
+}
+
+
+void
+_tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_LIGHT)
+ gl_update_lighting_function(ctx);
+
+ if (new_state & _NEW_ARRAY)
+ gl_update_client_state( ctx );
+
+ if (new_state & _NEW_TEXTURE)
+ if (ctx->_Enabled & ENABLE_TEXGEN_ANY)
+ _tnl_update_texgen( ctx );
+
+ if (new_state & (_NEW_LIGHT|_NEW_TEXTURE|_NEW_FOG|
+ _DD_NEW_TRI_LIGHT_TWOSIDE |
+ _DD_NEW_SEPERATE_SPECULAR |
+ _DD_NEW_TRI_UNFILLED ))
+ gl_update_clipmask(ctx);
+
+ if (new_state & _TNL_NEW_NORMAL_TRANSFORM)
+ _tnl_update_normal_transform( ctx );
+
+ gl_update_pipelines(ctx);
+}
+
+void
+_tnl_MakeCurrent( GLcontext *ctx,
+ GLframebuffer *drawBuffer,
+ GLframebuffer *readBuffer )
+{
+#ifndef THREADS
+ SET_IMMEDIATE(newCtx, newCtx->input);
+#endif
+}
diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h
new file mode 100644
index 00000000000..992c2a58f9b
--- /dev/null
+++ b/src/mesa/tnl/t_context.h
@@ -0,0 +1,629 @@
+
+/* $Id: t_context.h,v 1.1 2000/11/16 21:05:42 keithw Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999 Brian Paul 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
+ * BRIAN PAUL 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_CONTEXT_H
+#define _T_CONTEXT_H
+
+#include "glheader.h"
+#include "types.h"
+
+#include "math/m_matrix.h"
+#include "math/m_vector.h"
+#include "math/m_xform.h"
+
+#include "t_trans_elt.h"
+
+
+
+/*
+ * Bits to indicate which faces a vertex participates in,
+ * what facing the primitive provoked by that vertex has,
+ * and some misc. flags.
+ */
+#define VERT_FACE_FRONT 0x1 /* is in a front-color primitive */
+#define VERT_FACE_REAR 0x2 /* is in a rear-color primitive */
+#define PRIM_FACE_FRONT 0x4 /* use front color */
+#define PRIM_FACE_REAR 0x8 /* use rear color */
+#define PRIM_CLIPPED 0x10 /* needs clipping */
+#define PRIM_USER_CLIPPED CLIP_USER_BIT /* 0x40 */
+
+
+#define PRIM_FLAG_SHIFT 2
+#define PRIM_FACE_FLAGS (PRIM_FACE_FRONT|PRIM_FACE_REAR)
+#define VERT_FACE_FLAGS (VERT_FACE_FRONT|VERT_FACE_REAR)
+
+#define PRIM_ANY_CLIP (PRIM_CLIPPED|PRIM_USER_CLIPPED)
+#define PRIM_NOT_CULLED (PRIM_ANY_CLIP|PRIM_FACE_FLAGS)
+
+/* Flags for VB->CullMode.
+ */
+#define CULL_MASK_ACTIVE 0x1
+#define COMPACTED_NORMALS 0x2
+#define CLIP_MASK_ACTIVE 0x4
+
+/* Flags for selecting a shading function. The first two bits are
+ * shared with the cull mode (ie. cull_mask_active and
+ * compacted_normals.)
+ */
+#define SHADE_TWOSIDE 0x4
+
+
+/* KW: Flags that describe the current vertex state, and the contents
+ * of a vertex in a vertex-cassette.
+ *
+ * For really major expansion, consider a 'VERT_ADDITIONAL_FLAGS' flag,
+ * which means there is data in another flags array (eg, extra_flags[]).
+ */
+
+#define VERT_OBJ_2 0x1 /* glVertex2 */
+#define VERT_OBJ_3 0x2 /* glVertex3 */
+#define VERT_OBJ_4 0x4 /* glVertex4 */
+#define VERT_BEGIN 0x8 /* glBegin */
+#define VERT_END 0x10 /* glEnd */
+#define VERT_ELT 0x20 /* glArrayElement */
+#define VERT_RGBA 0x40 /* glColor */
+#define VERT_NORM 0x80 /* glNormal */
+#define VERT_INDEX 0x100 /* glIndex */
+#define VERT_EDGE 0x200 /* glEdgeFlag */
+#define VERT_MATERIAL 0x400 /* glMaterial */
+#define VERT_END_VB 0x800 /* end vb marker */
+#define VERT_TEX0_12 0x1000
+#define VERT_TEX0_3 0x2000
+#define VERT_TEX0_4 0x4000
+#define VERT_TEX1_12 0x8000
+#define VERT_TEX1_3 0x10000
+#define VERT_TEX1_4 0x20000
+#define VERT_TEX2_12 0x40000
+#define VERT_TEX2_3 0x80000
+#define VERT_TEX2_4 0x100000
+#define VERT_TEX3_12 0x200000
+#define VERT_TEX3_3 0x400000
+#define VERT_TEX3_4 0x800000
+#define VERT_EVAL_C1 0x1000000 /* could reuse OBJ bits for this? */
+#define VERT_EVAL_C2 0x2000000 /* - or just use 3 bits */
+#define VERT_EVAL_P1 0x4000000 /* */
+#define VERT_EVAL_P2 0x8000000 /* */
+#define VERT_SPEC_RGB 0x10000000
+#define VERT_FOG_COORD 0x20000000 /* internal use only, currently */
+
+#define VERT_EYE VERT_BEGIN /* reuse */
+#define VERT_WIN VERT_END /* reuse */
+#define VERT_SETUP_FULL VERT_EVAL_P1 /* Rastersetup has been done */
+#define VERT_PRECALC_DATA VERT_END_VB /* reuse */
+
+/* Shorthands.
+ */
+#define VERT_TEX0_SHIFT 11
+
+#define VERT_EVAL_ANY (VERT_EVAL_C1|VERT_EVAL_P1| \
+ VERT_EVAL_C2|VERT_EVAL_P2)
+
+#define VERT_OBJ_23 (VERT_OBJ_3|VERT_OBJ_2)
+#define VERT_OBJ_234 (VERT_OBJ_4|VERT_OBJ_23)
+#define VERT_OBJ_ANY VERT_OBJ_2
+
+#define VERT_TEX0_123 (VERT_TEX0_3|VERT_TEX0_12)
+#define VERT_TEX0_1234 (VERT_TEX0_4|VERT_TEX0_123)
+#define VERT_TEX0_ANY VERT_TEX0_12
+
+#define VERT_TEX1_123 (VERT_TEX1_3|VERT_TEX1_12)
+#define VERT_TEX1_1234 (VERT_TEX1_4|VERT_TEX1_123)
+#define VERT_TEX1_ANY VERT_TEX1_12
+
+#define VERT_TEX2_123 (VERT_TEX2_3|VERT_TEX2_12)
+#define VERT_TEX2_1234 (VERT_TEX2_4|VERT_TEX2_123)
+#define VERT_TEX2_ANY VERT_TEX2_12
+
+#define VERT_TEX3_123 (VERT_TEX3_3|VERT_TEX3_12)
+#define VERT_TEX3_1234 (VERT_TEX3_4|VERT_TEX3_123)
+#define VERT_TEX3_ANY VERT_TEX3_12
+
+#define NR_TEXSIZE_BITS 3
+#define VERT_TEX_ANY(i) (VERT_TEX0_ANY << ((i) * NR_TEXSIZE_BITS))
+
+#define VERT_FIXUP (VERT_TEX0_ANY | \
+ VERT_TEX1_ANY | \
+ VERT_TEX2_ANY | \
+ VERT_TEX3_ANY | \
+ VERT_RGBA | \
+ VERT_SPEC_RGB | \
+ VERT_FOG_COORD | \
+ VERT_INDEX | \
+ VERT_EDGE | \
+ VERT_NORM)
+
+#define VERT_DATA (VERT_TEX0_ANY | \
+ VERT_TEX1_ANY | \
+ VERT_TEX2_ANY | \
+ VERT_TEX3_ANY | \
+ VERT_RGBA | \
+ VERT_SPEC_RGB | \
+ VERT_FOG_COORD | \
+ VERT_INDEX | \
+ VERT_EDGE | \
+ VERT_NORM | \
+ VERT_OBJ_ANY | \
+ VERT_MATERIAL | \
+ VERT_ELT | \
+ VERT_EVAL_ANY | \
+ VERT_FOG_COORD)
+
+
+/* For beginstate
+ */
+#define VERT_BEGIN_0 0x1 /* glBegin (if initially inside beg/end) */
+#define VERT_BEGIN_1 0x2 /* glBegin (if initially outside beg/end) */
+#define VERT_ERROR_0 0x4 /* invalid_operation in initial state 0 */
+#define VERT_ERROR_1 0x8 /* invalid_operation in initial state 1 */
+
+
+struct gl_pipeline;
+struct tnl_context;
+
+/**
+ ** Vertex buffer/array structures
+ **/
+
+struct vertex_data
+{
+ GLfloat (*Obj)[4];
+ GLfloat (*Normal)[3];
+ GLchan (*Color)[4];
+ GLuint *Index;
+ GLubyte *EdgeFlag;
+ GLfloat (*TexCoord[MAX_TEXTURE_UNITS])[4];
+ GLuint *Elt;
+ GLfloat *FogCoord;
+ GLubyte (*SecondaryColor)[4];
+};
+
+struct vertex_arrays
+{
+ GLvector4f Obj;
+ GLvector3f Normal;
+ GLvector4ub Color;
+ GLvector1ui Index;
+ GLvector1ub EdgeFlag;
+ GLvector4f TexCoord[MAX_TEXTURE_UNITS];
+ GLvector1ui Elt;
+ GLvector4ub SecondaryColor;
+ GLvector1f FogCoord;
+};
+
+struct vertex_array_pointers
+{
+ GLvector4f *Obj;
+ GLvector3f *Normal;
+ GLvector4ub *Color;
+ GLvector1ui *Index;
+ GLvector1ub *EdgeFlag;
+ GLvector4f *TexCoord[MAX_TEXTURE_UNITS];
+ GLvector1ui *Elt;
+ GLvector4ub *SecondaryColor;
+ GLvector1f *FogCoord;
+};
+
+/* Values for VB->Type */
+enum {
+ VB_IMMEDIATE,
+ VB_CVA_PRECALC
+};
+
+
+/* Values for immediate->BeginState */
+#define VERT_BEGIN_0 0x1 /* glBegin (if initially inside beg/end) */
+#define VERT_BEGIN_1 0x2 /* glBegin (if initially outside beg/end) */
+#define VERT_ERROR_0 0x4 /* invalid_operation in initial state 0 */
+#define VERT_ERROR_1 0x8 /* invalid_operation in initial state 1 */
+
+
+/* KW: Represents everything that can take place between a begin and
+ * end, and can represent multiple begin/end pairs. This plus *any*
+ * state variable (GLcontext) should be all you need to replay the
+ * represented begin/end pairs as if they took place in that state.
+ *
+ * Thus this is sufficient for both immediate and compiled modes, but
+ * we could/should throw some elements away for compiled mode if we
+ * know they were empty.
+ */
+struct immediate
+{
+ struct immediate *next; /* for cache of free IM's */
+ GLuint id, ref_count;
+
+ /* This must be saved when immediates are shared in display lists.
+ */
+ GLuint Start, Count;
+ GLuint LastData; /* count or count+1 */
+ GLuint AndFlag, OrFlag, BeginState;
+ GLuint LastPrimitive;
+
+ GLuint ArrayAndFlags; /* precalc'ed for glArrayElt */
+ GLuint ArrayIncr;
+ GLuint ArrayEltFlush;
+ GLuint FlushElt;
+
+ GLuint TF1[MAX_TEXTURE_UNITS]; /* precalc'ed for glTexCoord */
+ GLuint TF2[MAX_TEXTURE_UNITS];
+ GLuint TF3[MAX_TEXTURE_UNITS];
+ GLuint TF4[MAX_TEXTURE_UNITS];
+
+ GLuint Primitive[VB_SIZE]; /* GLubyte would do... */
+ GLuint NextPrimitive[VB_SIZE];
+
+ /* allocate storage for these on demand:
+ */
+ struct gl_material (*Material)[2];
+ GLuint *MaterialMask;
+
+ GLfloat (*TexCoordPtr[MAX_TEXTURE_UNITS])[4];
+
+ struct vertex_arrays v;
+
+ struct __GLcontextRec *backref;
+
+ /* Normal lengths, zero if not available.
+ */
+ GLfloat *NormalLengths;
+ GLuint LastCalcedLength;
+
+ GLuint Flag[VB_SIZE]; /* bitwise-OR of VERT_ flags */
+ GLchan Color[VB_SIZE][4];
+ GLfloat Obj[VB_SIZE][4];
+ GLfloat Normal[VB_SIZE][3];
+ GLfloat TexCoord[MAX_TEXTURE_UNITS][VB_SIZE][4];
+ GLuint Elt[VB_SIZE];
+ GLubyte EdgeFlag[VB_SIZE];
+ GLuint Index[VB_SIZE];
+ GLubyte SecondaryColor[VB_SIZE][4];
+ GLfloat FogCoord[VB_SIZE];
+};
+
+
+/* Not so big on storage these days, although still has pointers to
+ * arrays used for temporary results.
+ */
+typedef struct vertex_buffer
+{
+ /* Backpointers.
+ */
+ struct __GLcontextRec *ctx;
+ struct tnl_context *tnlctx;
+
+ /* Driver_data is allocated in Driver.RegisterVB(), if required.
+ */
+ void *driver_data;
+
+ /* List of operations to process vertices in current state.
+ */
+ struct gl_pipeline *pipeline;
+
+ /* Temporary storage used by immediate mode functions and various
+ * operations in the pipeline.
+ */
+ struct immediate *IM;
+ struct vertex_array_pointers store;
+
+ /* Where to find outstanding untransformed vertices.
+ */
+ struct immediate *prev_buffer;
+
+ GLuint Type; /* Either VB_IMMEDIATE or VB_CVA_PRECALC */
+
+ GLuint Size, Start, Count;
+ GLuint Free, FirstFree;
+ GLuint CopyStart;
+ GLuint Parity, Ovf;
+ GLuint PurgeFlags;
+ GLuint IndirectCount; /* defaults to count */
+ GLuint OrFlag, SavedOrFlag;
+ GLuint EarlyCull;
+ GLuint Culled, CullDone;
+
+ /* Pointers to input data - default to buffers in 'im' above.
+ */
+ GLvector4f *ObjPtr;
+ GLvector3f *NormalPtr;
+ GLvector4ub *ColorPtr;
+ GLvector1ui *IndexPtr;
+ GLvector1ub *EdgeFlagPtr;
+ GLvector4f *TexCoordPtr[MAX_TEXTURE_UNITS];
+ GLvector1ui *EltPtr;
+ GLvector4ub *SecondaryColorPtr;
+ GLvector1f *FogCoordPtr;
+ GLuint *Flag, FlagMax;
+ struct gl_material (*Material)[2];
+ GLuint *MaterialMask;
+
+ GLuint *NextPrimitive;
+ GLuint *Primitive;
+ GLuint LastPrimitive;
+
+ GLfloat (*BoundsPtr)[3]; /* Bounds for cull check */
+ GLfloat *NormalLengthPtr; /* Array of precomputed inv. normal lengths */
+
+ /* Holds malloced storage for pipeline data not supplied by
+ * the immediate struct.
+ */
+ GLvector4f Eye;
+ GLvector4f Clip;
+ GLvector4f Win;
+ GLvector4ub BColor; /* not used in cva vb's */
+ GLvector1ui BIndex; /* not used in cva vb's */
+ GLvector4ub BSecondary; /* not used in cva vb's */
+
+ /* Temporary storage - may point into IM, or be dynamically
+ * allocated (for cva).
+ */
+ GLubyte *ClipMask;
+ GLubyte *UserClipMask;
+
+ /* Internal values. Where these point depends on whether
+ * there were any identity matrices defined as transformations
+ * in the pipeline.
+ */
+ GLvector4f *EyePtr;
+ GLvector4f *ClipPtr;
+ GLvector4f *Unprojected;
+ GLvector4f *Projected;
+ GLvector4f *CurrentTexCoord;
+ GLuint *Indirect; /* For eval rescue and cva render */
+
+ /* Currently active colors
+ */
+ GLvector4ub *Color[2];
+ GLvector1ui *Index[2];
+ GLvector4ub *SecondaryColor[2];
+
+ /* Storage for colors which have been lit but not yet fogged.
+ * Required for CVA, just point into store for normal VB's.
+ */
+ GLvector4ub *LitColor[2];
+ GLvector1ui *LitIndex[2];
+ GLvector4ub *LitSecondary[2];
+
+ /* Temporary values used in texgen.
+ */
+ GLfloat (*tmp_f)[3];
+ GLfloat *tmp_m;
+
+ /* Temporary values used in eval.
+ */
+ GLuint *EvaluatedFlags;
+
+ /* Not used for cva:
+ */
+ GLubyte *NormCullStart;
+ GLubyte *CullMask; /* Results of vertex culling */
+ GLubyte *NormCullMask; /* Compressed onto shared normals */
+
+ GLubyte ClipOrMask; /* bitwise-OR of all ClipMask[] values */
+ GLubyte ClipAndMask; /* bitwise-AND of all ClipMask[] values */
+ GLubyte CullFlag[2];
+ GLubyte CullMode; /* see flags below */
+
+ GLuint CopyCount; /* max 3 vertices to copy after transform */
+ GLuint Copy[3];
+ GLfloat CopyProj[3][4]; /* temporary store for projected clip coords */
+
+ /* Hooks for module private data
+ */
+ void *swsetup_vb;
+
+} TNLvertexbuffer;
+
+
+typedef void (*gl_shade_func)( struct vertex_buffer *VB );
+
+typedef void (*clip_interp_func)( struct vertex_buffer *VB, GLuint dst,
+ GLfloat t, GLuint in, GLuint out );
+
+typedef GLuint (*clip_line_func)( struct vertex_buffer *VB,
+ GLuint *i, GLuint *j,
+ GLubyte mask);
+
+typedef GLuint (*clip_poly_func)( struct vertex_buffer *VB,
+ GLuint n, GLuint vlist[],
+ GLubyte mask );
+
+
+#define MAX_PIPELINE_STAGES 30
+
+#define PIPE_IMMEDIATE 0x1
+#define PIPE_PRECALC 0x2
+
+#define PIPE_OP_VERT_XFORM 0x1
+#define PIPE_OP_NORM_XFORM 0x2
+#define PIPE_OP_LIGHT 0x4
+#define PIPE_OP_FOG 0x8
+#define PIPE_OP_TEX0 0x10
+#define PIPE_OP_TEX1 0x20
+#define PIPE_OP_TEX2 0x40
+#define PIPE_OP_TEX3 0x80
+#define PIPE_OP_RAST_SETUP_0 0x100
+#define PIPE_OP_RAST_SETUP_1 0x200
+#define PIPE_OP_RENDER 0x400
+#define PIPE_OP_CVA_PREPARE 0x800
+
+
+
+struct gl_pipeline_stage {
+ const char *name;
+ GLuint ops; /* PIPE_OP flags */
+ GLuint type; /* VERT flags */
+ GLuint special; /* VERT flags - force update_inputs() */
+ GLuint state_change; /* state flags - trigger update_inputs() */
+ GLuint cva_state_change; /* state flags - recalc cva buffer */
+ GLuint elt_forbidden_inputs; /* VERT flags - force a pipeline recalc */
+ GLuint pre_forbidden_inputs; /* VERT flags - force a pipeline recalc */
+ GLuint active; /* VERT flags */
+ GLuint inputs; /* VERT flags */
+ GLuint outputs; /* VERT flags */
+ void (*check)( GLcontext *ctx, struct gl_pipeline_stage * );
+ void (*run)( struct vertex_buffer *VB );
+};
+
+
+struct gl_pipeline {
+ GLuint state_change; /* state changes which require recalc */
+ GLuint cva_state_change; /* ... which require re-run */
+ GLuint forbidden_inputs; /* inputs which require recalc */
+ GLuint ops; /* what gets done in this pipe */
+ GLuint changed_ops;
+ GLuint inputs;
+ GLuint outputs;
+ GLuint new_inputs;
+ GLuint new_outputs;
+ GLuint fallback;
+ GLuint type;
+ GLuint pipeline_valid:1;
+ GLuint data_valid:1;
+ GLuint copy_transformed_data:1;
+ GLuint replay_copied_vertices:1;
+ GLuint new_state; /* state changes since last recalc */
+ struct gl_pipeline_stage *stages[MAX_PIPELINE_STAGES];
+};
+
+
+
+/* All fields are derived.
+ */
+struct gl_cva {
+ struct gl_pipeline pre;
+ struct gl_pipeline elt;
+
+ struct gl_client_array Elt;
+ trans_1ui_func EltFunc;
+
+ struct vertex_buffer *VB;
+ struct vertex_arrays v;
+ struct vertex_data store;
+
+ GLuint elt_count;
+ GLenum elt_mode;
+ GLuint elt_size;
+
+ GLuint forbidden_inputs;
+ GLuint orflag;
+ GLuint merge;
+
+ GLuint lock_changed;
+ GLuint last_orflag;
+ GLuint last_array_flags;
+ GLuint last_array_new_state;
+};
+
+
+
+typedef void (*texgen_func)( struct vertex_buffer *VB,
+ GLuint textureSet);
+
+
+
+typedef struct tnl_context {
+
+ GLuint _ArrayFlag[VB_SIZE]; /* crock */
+ GLuint _ArrayFlags;
+ GLuint _ArraySummary; /* Like flags, but no size information */
+ GLuint _ArrayNewState; /* Tracks which arrays have been changed. */
+
+
+ /* Pipeline stages - shared between the two pipelines,
+ * which live in CVA.
+ */
+ struct gl_pipeline_stage PipelineStage[MAX_PIPELINE_STAGES];
+ GLuint NrPipelineStages;
+
+ /* Per-texunit derived state.
+ */
+ GLuint _TexgenSize[MAX_TEXTURE_UNITS];
+ GLuint _TexgenHoles[MAX_TEXTURE_UNITS];
+ texgen_func *_TexgenFunc[MAX_TEXTURE_UNITS];
+
+
+ /* Display list extensions
+ */
+ GLuint opcode_vertex_cassette;
+
+ /* Cva
+ */
+ struct gl_cva CVA;
+ GLboolean CompileCVAFlag;
+
+ clip_poly_func *_poly_clip_tab;
+ clip_line_func *_line_clip_tab;
+ clip_interp_func _ClipInterpFunc; /* Clip interpolation function */
+ normal_func *_NormalTransform;
+ gl_shade_func *_shade_func_tab; /* Current shading function table */
+
+ GLenum _CurrentPrimitive; /* Prim or GL_POLYGON+1 */
+ GLuint _CurrentFlag;
+
+ GLuint _RenderFlags; /* Active inputs to render stage */
+
+ /* Cache of unused immediate structs */
+ struct immediate *freed_im_queue;
+ GLuint nr_im_queued;
+
+} TNLcontext;
+
+
+
+#define TNL_CONTEXT(ctx) ((TNLcontext *)(ctx->swtnl_context))
+#define TNL_CURRENT_IM(ctx) ((struct immediate *)(ctx->swtnl_im))
+#define TNL_VB(ctx) ((struct vertex_buffer *)(ctx->swtnl_vb))
+
+extern void _tnl_reset_immediate( GLcontext *ctx );
+extern GLboolean _tnl_flush_vertices( GLcontext *ctx, GLuint flush_flags );
+
+
+extern void
+_tnl_MakeCurrent( GLcontext *ctx,
+ GLframebuffer *drawBuffer,
+ GLframebuffer *readBuffer );
+
+
+extern void
+_tnl_LightingSpaceChange( GLcontext *ctx );
+
+/*
+ * Macros for fetching current input buffer.
+ */
+#ifdef THREADS
+#define GET_IMMEDIATE struct immediate *IM = TNL_CURRENT_IM(((GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context())))
+#define SET_IMMEDIATE(ctx, im) ctx->swtnl_im = (void *)im
+#else
+extern struct immediate *_mesa_CurrentInput;
+#define GET_IMMEDIATE struct immediate *IM = _mesa_CurrentInput
+#define SET_IMMEDIATE(ctx, im) \
+do { \
+ TNL_CURRENT_IM(ctx) = im; \
+ _mesa_CurrentInput = im; \
+} while (0)
+#endif
+
+#endif
diff --git a/src/mesa/tnl/t_pipeline.c b/src/mesa/tnl/t_pipeline.c
new file mode 100644
index 00000000000..03c93911b93
--- /dev/null
+++ b/src/mesa/tnl/t_pipeline.c
@@ -0,0 +1,496 @@
+/* $Id: t_pipeline.c,v 1.1 2000/11/16 21:05:42 keithw Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2000 Brian Paul 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
+ * BRIAN PAUL 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.
+ */
+
+/* Dynamic pipelines, support for CVA.
+ * Copyright (C) 1999 Keith Whitwell.
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "mem.h"
+#include "mmath.h"
+#include "state.h"
+#include "types.h"
+
+#include "math/m_translate.h"
+#include "math/m_xform.h"
+
+#include "t_bbox.h"
+#include "t_clip.h"
+#include "t_cva.h"
+#include "t_fog.h"
+#include "t_light.h"
+#include "t_pipeline.h"
+#include "t_shade.h"
+#include "t_stages.h"
+#include "t_vbcull.h"
+#include "t_vbindirect.h"
+#include "t_vbrender.h"
+#include "t_vbxform.h"
+
+
+
+
+
+void gl_print_pipe_ops( const char *msg, GLuint flags )
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & PIPE_OP_CVA_PREPARE) ? "cva-prepare, " : "",
+ (flags & PIPE_OP_VERT_XFORM) ? "vert-xform, " : "",
+ (flags & PIPE_OP_NORM_XFORM) ? "norm-xform, " : "",
+ (flags & PIPE_OP_LIGHT) ? "light, " : "",
+ (flags & PIPE_OP_FOG) ? "fog, " : "",
+ (flags & PIPE_OP_TEX0) ? "tex-0, " : "",
+ (flags & PIPE_OP_TEX1) ? "tex-1, " : "",
+ (flags & PIPE_OP_RAST_SETUP_0) ? "rast-0, " : "",
+ (flags & PIPE_OP_RAST_SETUP_1) ? "rast-1, " : "",
+ (flags & PIPE_OP_RENDER) ? "render, " : "");
+
+}
+
+
+
+/* Have to reset only those parts of the vb which are being recalculated.
+ */
+void gl_reset_cva_vb( struct vertex_buffer *VB, GLuint stages )
+{
+ GLcontext *ctx = VB->ctx;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_PIPELINE)
+ gl_print_pipe_ops( "reset cva vb", stages );
+
+ if (stages & PIPE_OP_VERT_XFORM)
+ {
+ if (VB->ClipOrMask & CLIP_USER_BIT)
+ MEMSET(VB->UserClipMask, 0, VB->Count);
+
+ VB->ClipOrMask = 0;
+ VB->ClipAndMask = CLIP_ALL_BITS;
+ VB->CullMode = 0;
+ VB->CullFlag[0] = VB->CullFlag[1] = 0;
+ VB->Culled = 0;
+ }
+
+ if (stages & PIPE_OP_NORM_XFORM) {
+ VB->NormalPtr = &tnl->CVA.v.Normal;
+ }
+
+ if (stages & PIPE_OP_LIGHT)
+ {
+ VB->ColorPtr = VB->Color[0] = VB->Color[1] = &tnl->CVA.v.Color;
+ VB->IndexPtr = VB->Index[0] = VB->Index[1] = &tnl->CVA.v.Index;
+ }
+ else if (stages & PIPE_OP_FOG)
+ {
+ if (ctx->Light.Enabled) {
+ VB->Color[0] = VB->LitColor[0];
+ VB->Color[1] = VB->LitColor[1];
+ VB->Index[0] = VB->LitIndex[0];
+ VB->Index[1] = VB->LitIndex[1];
+ } else {
+ VB->Color[0] = VB->Color[1] = &tnl->CVA.v.Color;
+ VB->Index[0] = VB->Index[1] = &tnl->CVA.v.Index;
+ }
+ VB->ColorPtr = VB->Color[0];
+ VB->IndexPtr = VB->Index[0];
+ }
+}
+
+
+
+
+
+
+static void pipeline_ctr( struct gl_pipeline *p, GLcontext *ctx, GLuint type )
+{
+ GLuint i;
+ (void) ctx;
+
+ p->state_change = 0;
+ p->cva_state_change = 0;
+ p->inputs = 0;
+ p->outputs = 0;
+ p->type = type;
+ p->ops = 0;
+
+ for (i = 0 ; i < gl_default_nr_stages ; i++)
+ p->state_change |= gl_default_pipeline[i].state_change;
+}
+
+
+void _tnl_pipeline_init( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ MEMCPY( tnl->PipelineStage,
+ gl_default_pipeline,
+ sizeof(*gl_default_pipeline) * gl_default_nr_stages );
+
+ tnl->NrPipelineStages = gl_default_nr_stages;
+
+ pipeline_ctr( &tnl->CVA.elt, ctx, PIPE_IMMEDIATE);
+ pipeline_ctr( &tnl->CVA.pre, ctx, PIPE_PRECALC );
+}
+
+
+
+#define MINIMAL_VERT_DATA (VERT_DATA & ~(VERT_TEX0_4 | \
+ VERT_TEX1_4 | \
+ VERT_TEX2_4 | \
+ VERT_TEX3_4 | \
+ VERT_EVAL_ANY))
+
+#define VERT_CURRENT_DATA (VERT_TEX0_1234 | \
+ VERT_TEX1_1234 | \
+ VERT_TEX2_1234 | \
+ VERT_TEX3_1234 | \
+ VERT_RGBA | \
+ VERT_SPEC_RGB | \
+ VERT_FOG_COORD | \
+ VERT_INDEX | \
+ VERT_EDGE | \
+ VERT_NORM | \
+ VERT_MATERIAL)
+
+/* Called prior to every recomputation of the CVA precalc data, except where
+ * the driver is able to calculate the pipeline unassisted.
+ */
+static void build_full_precalc_pipeline( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
+ struct gl_cva *cva = &tnl->CVA;
+ struct gl_pipeline *pre = &cva->pre;
+ struct gl_pipeline_stage **stages = pre->stages;
+ GLuint i;
+ GLuint newstate = pre->new_state;
+ GLuint changed_ops = 0;
+ GLuint oldoutputs = pre->outputs;
+ GLuint oldinputs = pre->inputs;
+ GLuint fallback = (VERT_CURRENT_DATA & tnl->_CurrentFlag &
+ ~tnl->_ArraySummary);
+ GLuint changed_outputs = (tnl->_ArrayNewState |
+ (fallback & cva->orflag));
+ GLuint available = fallback | tnl->_ArrayFlags;
+
+ pre->cva_state_change = 0;
+ pre->ops = 0;
+ pre->outputs = 0;
+ pre->inputs = 0;
+ pre->forbidden_inputs = 0;
+ pre->fallback = 0;
+
+ /* KW: Disable data reuse during Mesa reorg. Make this more readable...
+ */
+ newstate = ~0;
+
+ if (tnl->_ArraySummary & VERT_ELT)
+ cva->orflag &= VERT_MATERIAL;
+
+ cva->orflag &= ~(tnl->_ArraySummary & ~VERT_OBJ_ANY);
+ available &= ~cva->orflag;
+
+ pre->outputs = available;
+ pre->inputs = available;
+
+ if (MESA_VERBOSE & VERBOSE_PIPELINE) {
+ fprintf(stderr, ": Rebuild pipeline\n");
+ gl_print_vert_flags("orflag", cva->orflag);
+ }
+
+
+
+ /* If something changes in the pipeline, tag all subsequent stages
+ * using this value for recalcuation. Also used to build the full
+ * pipeline by setting newstate and newinputs to ~0.
+ *
+ * Because all intermediate values are buffered, the new inputs
+ * are enough to fully specify what needs to be calculated, and a
+ * single pass identifies all stages requiring recalculation.
+ */
+ for (i = 0 ; i < tnl->NrPipelineStages ; i++)
+ {
+ pipeline[i].check(ctx, &pipeline[i]);
+
+ if (pipeline[i].type & PIPE_PRECALC)
+ {
+ if ((newstate & pipeline[i].cva_state_change) ||
+ (changed_outputs & pipeline[i].inputs) ||
+ !pipeline[i].inputs)
+ {
+ changed_ops |= pipeline[i].ops;
+ changed_outputs |= pipeline[i].outputs;
+ pipeline[i].active &= ~PIPE_PRECALC;
+
+ if ((pipeline[i].inputs & ~available) == 0 &&
+ (pipeline[i].ops & pre->ops) == 0)
+ {
+ pipeline[i].active |= PIPE_PRECALC;
+ *stages++ = &pipeline[i];
+ }
+ }
+
+ /* Incompatible with multiple stages structs implementing
+ * the same stage.
+ */
+ available &= ~pipeline[i].outputs;
+ pre->outputs &= ~pipeline[i].outputs;
+
+ if (pipeline[i].active & PIPE_PRECALC) {
+ pre->ops |= pipeline[i].ops;
+ pre->outputs |= pipeline[i].outputs;
+ available |= pipeline[i].outputs;
+ pre->forbidden_inputs |= pipeline[i].pre_forbidden_inputs;
+ }
+ }
+ else if (pipeline[i].active & PIPE_PRECALC)
+ {
+ pipeline[i].active &= ~PIPE_PRECALC;
+ changed_outputs |= pipeline[i].outputs;
+ changed_ops |= pipeline[i].ops;
+ }
+ }
+
+ *stages = 0;
+
+ pre->new_outputs = pre->outputs & (changed_outputs | ~oldoutputs);
+ pre->new_inputs = pre->inputs & ~oldinputs;
+ pre->fallback = pre->inputs & fallback;
+ pre->forbidden_inputs |= pre->inputs & fallback;
+
+ pre->changed_ops = changed_ops;
+}
+
+void gl_build_precalc_pipeline( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct gl_pipeline *pre = &tnl->CVA.pre;
+ struct gl_pipeline *elt = &tnl->CVA.elt;
+
+ if (!ctx->Driver.BuildPrecalcPipeline ||
+ !ctx->Driver.BuildPrecalcPipeline( ctx ))
+ build_full_precalc_pipeline( ctx );
+
+ pre->data_valid = 0;
+ pre->pipeline_valid = 1;
+ elt->pipeline_valid = 0;
+
+ tnl->CVA.orflag = 0;
+
+ if (MESA_VERBOSE&VERBOSE_PIPELINE)
+ gl_print_pipeline( ctx, pre );
+}
+
+
+static void build_full_immediate_pipeline( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
+ struct gl_cva *cva = &tnl->CVA;
+ struct gl_pipeline *pre = &cva->pre;
+ struct gl_pipeline *elt = &cva->elt;
+ struct gl_pipeline_stage **stages = elt->stages;
+ GLuint i;
+ GLuint newstate = elt->new_state;
+ GLuint active_ops = 0;
+ GLuint available = cva->orflag | MINIMAL_VERT_DATA;
+ GLuint generated = 0;
+ GLuint is_elt = 0;
+
+ if (pre->data_valid && tnl->CompileCVAFlag) {
+ is_elt = 1;
+ active_ops = cva->pre.ops;
+ available |= pre->outputs | VERT_PRECALC_DATA;
+ }
+
+
+ elt->outputs = 0; /* not used */
+ elt->inputs = 0;
+
+ for (i = 0 ; i < tnl->NrPipelineStages ; i++) {
+ pipeline[i].active &= ~PIPE_IMMEDIATE;
+
+ if ((pipeline[i].state_change & newstate) ||
+ (pipeline[i].elt_forbidden_inputs & available))
+ {
+ pipeline[i].check(ctx, &pipeline[i]);
+ }
+
+ if ((pipeline[i].type & PIPE_IMMEDIATE) &&
+ (pipeline[i].ops & active_ops) == 0 &&
+ (pipeline[i].elt_forbidden_inputs & available) == 0
+ )
+ {
+ if (pipeline[i].inputs & ~available)
+ elt->forbidden_inputs |= pipeline[i].inputs & ~available;
+ else
+ {
+ elt->inputs |= pipeline[i].inputs & ~generated;
+ elt->forbidden_inputs |= pipeline[i].elt_forbidden_inputs;
+ pipeline[i].active |= PIPE_IMMEDIATE;
+ *stages++ = &pipeline[i];
+ generated |= pipeline[i].outputs;
+ available |= pipeline[i].outputs;
+ active_ops |= pipeline[i].ops;
+ }
+ }
+ }
+
+ *stages = 0;
+
+ elt->copy_transformed_data = 1;
+ elt->replay_copied_vertices = 0;
+
+ if (is_elt) {
+ cva->merge = elt->inputs & pre->outputs;
+ elt->ops = active_ops & ~pre->ops;
+ }
+}
+
+
+
+void gl_build_immediate_pipeline( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct gl_pipeline *elt = &tnl->CVA.elt;
+
+ if (!ctx->Driver.BuildEltPipeline ||
+ !ctx->Driver.BuildEltPipeline( ctx )) {
+ build_full_immediate_pipeline( ctx );
+ }
+
+ elt->pipeline_valid = 1;
+ tnl->CVA.orflag = 0;
+
+ if (MESA_VERBOSE&VERBOSE_PIPELINE)
+ gl_print_pipeline( ctx, elt );
+}
+
+#define INTERESTED ~0
+
+void gl_update_pipelines( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint newstate = ctx->NewState;
+ struct gl_cva *cva = &tnl->CVA;
+
+ newstate &= INTERESTED;
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_STATE))
+ gl_print_enable_flags("enabled", ctx->_Enabled);
+
+ if (newstate ||
+ cva->lock_changed ||
+ cva->orflag != cva->last_orflag ||
+ tnl->_ArrayFlags != cva->last_array_flags)
+ {
+ GLuint flags = VERT_WIN;
+
+ if (ctx->Visual.RGBAflag) {
+ flags |= VERT_RGBA;
+ if (ctx->_TriangleCaps && DD_SEPERATE_SPECULAR)
+ flags |= VERT_SPEC_RGB;
+ } else
+ flags |= VERT_INDEX;
+
+ if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY)
+ flags |= VERT_TEX0_ANY;
+
+ if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY)
+ flags |= VERT_TEX1_ANY;
+
+#if MAX_TEXTURE_UNITS > 2
+ if (ctx->Texture._ReallyEnabled & TEXTURE2_ANY)
+ flags |= VERT_TEX2_ANY;
+#endif
+#if MAX_TEXTURE_UNITS > 3
+ if (ctx->Texture._ReallyEnabled & TEXTURE3_ANY)
+ flags |= VERT_TEX3_ANY;
+#endif
+
+ if (ctx->Polygon._Unfilled)
+ flags |= VERT_EDGE;
+
+ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
+ flags |= VERT_FOG_COORD;
+
+ if (ctx->RenderMode==GL_FEEDBACK) {
+ flags = (VERT_WIN | VERT_RGBA | VERT_INDEX | VERT_NORM | VERT_EDGE
+ | VERT_TEX0_ANY
+ | VERT_TEX1_ANY
+#if MAX_TEXTURE_UNITS > 2
+ | VERT_TEX2_ANY
+#endif
+#if MAX_TEXTURE_UNITS > 3
+ | VERT_TEX3_ANY
+#endif
+ );
+ }
+
+ tnl->_RenderFlags = flags;
+
+ cva->elt.new_state |= newstate;
+ cva->elt.pipeline_valid = 0;
+
+ cva->pre.new_state |= newstate;
+ cva->pre.forbidden_inputs = 0;
+ cva->pre.pipeline_valid = 0;
+ cva->lock_changed = 0;
+ }
+
+ if (tnl->_ArrayNewState != cva->last_array_new_state)
+ cva->pre.pipeline_valid = 0;
+
+ cva->pre.data_valid = 0;
+ cva->last_array_new_state = tnl->_ArrayNewState;
+ cva->last_orflag = cva->orflag;
+ cva->last_array_flags = tnl->_ArrayFlags;
+}
+
+void gl_run_pipeline( struct vertex_buffer *VB )
+{
+ struct gl_pipeline *pipe = VB->pipeline;
+ struct gl_pipeline_stage **stages = pipe->stages;
+ unsigned short x;
+
+ pipe->data_valid = 1; /* optimized stages might want to reset this. */
+
+ if (0) gl_print_pipeline( VB->ctx, pipe );
+
+ START_FAST_MATH(x);
+
+ for ( VB->Culled = 0; *stages && !VB->Culled ; stages++ )
+ (*stages)->run( VB );
+
+ END_FAST_MATH(x);
+
+ pipe->new_state = 0;
+}
+
diff --git a/src/mesa/tnl/t_pipeline.h b/src/mesa/tnl/t_pipeline.h
new file mode 100644
index 00000000000..36a2f066c23
--- /dev/null
+++ b/src/mesa/tnl/t_pipeline.h
@@ -0,0 +1,59 @@
+/* $Id: t_pipeline.h,v 1.1 2000/11/16 21:05:42 keithw Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999 Brian Paul 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
+ * BRIAN PAUL 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.
+ *
+ *
+ * Author:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+
+#ifndef _T_PIPELINE_H_
+#define _T_PIPELINE_H_
+
+#include "types.h"
+#include "t_context.h"
+
+extern void gl_update_materials( struct vertex_buffer *VB);
+
+extern void _tnl_pipeline_init( GLcontext *ctx );
+extern void gl_update_pipelines( GLcontext *ctx );
+
+extern void gl_build_precalc_pipeline( GLcontext *ctx );
+extern void gl_build_immediate_pipeline( GLcontext *ctx );
+
+extern void gl_print_vert_flags( const char *name, GLuint flags );
+extern void gl_print_pipeline( GLcontext *ctx, struct gl_pipeline *p );
+extern void gl_print_active_pipeline( GLcontext *ctx, struct gl_pipeline *p );
+
+extern void gl_run_pipeline( struct vertex_buffer *VB );
+
+extern void gl_clean_color( struct vertex_buffer *VB );
+
+extern void gl_reset_cva_vb( struct vertex_buffer *VB, GLuint stages );
+
+extern void gl_print_pipe_ops( const char *msg, GLuint flags );
+
+#endif
diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h
new file mode 100644
index 00000000000..dc46ef31346
--- /dev/null
+++ b/src/mesa/tnl/tnl.h
@@ -0,0 +1,48 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999 Brian Paul 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
+ * BRIAN PAUL 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.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#ifndef _TNL_H
+#define _TNL_H
+
+#include "types.h"
+
+
+
+/* These are the public-access functions exported from tnl. (Many
+ * more are currently hooked into dispatch directly by core code.)
+ */
+extern GLboolean
+_tnl_CreateContext( GLcontext *ctx );
+
+extern void
+_tnl_DestroyContext( GLcontext *ctx );
+
+extern void
+_tnl_InvalidateState( GLcontext *ctx, GLuint new_state );
+
+
+#endif