summaryrefslogtreecommitdiff
path: root/src/mesa/tnl
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2001-06-04 16:09:28 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2001-06-04 16:09:28 +0000
commit51b36396ae45f9ee9cec8d612787d038641dc6c8 (patch)
treef172ccf9a8536dfa168eb5c74b0f6f4ab9c946f5 /src/mesa/tnl
parentabd5134965665ad9f7154a08b13edfed15f00135 (diff)
Adaptor code that lets tnl convert compiled (display list) cassettes back
to glVertex() type calls. Allows driver-supplied tnl modules to avoid fallback on glCallList inside begin/end pairs. Still a little buggy...
Diffstat (limited to 'src/mesa/tnl')
-rw-r--r--src/mesa/tnl/t_context.c14
-rw-r--r--src/mesa/tnl/t_context.h3
-rw-r--r--src/mesa/tnl/t_imm_api.c6
-rw-r--r--src/mesa/tnl/t_imm_dlist.c295
-rw-r--r--src/mesa/tnl/t_imm_fixup.c89
-rw-r--r--src/mesa/tnl/t_imm_fixup.h5
-rw-r--r--src/mesa/tnl/tnl.h5
7 files changed, 305 insertions, 112 deletions
diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c
index 37b0483663..e842bd1422 100644
--- a/src/mesa/tnl/t_context.c
+++ b/src/mesa/tnl/t_context.c
@@ -1,4 +1,4 @@
-/* $Id: t_context.c,v 1.18 2001/05/11 08:11:31 keithw Exp $ */
+/* $Id: t_context.c,v 1.19 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
@@ -103,6 +103,7 @@ _tnl_CreateContext( GLcontext *ctx )
tnl->NeedProjCoords = GL_TRUE;
+ tnl->LoopbackDListCassettes = GL_FALSE;
/* Hook our functions into exec and compile dispatch tables.
*/
@@ -123,6 +124,8 @@ _tnl_CreateContext( GLcontext *ctx )
tnl->Driver.RenderTabElts = _tnl_render_tab_elts;
tnl->Driver.RenderTabVerts = _tnl_render_tab_verts;
+
+
return GL_TRUE;
}
@@ -210,3 +213,12 @@ _tnl_need_projected_coords( GLcontext *ctx, GLboolean mode )
_tnl_InvalidateState( ctx, _NEW_PROJECTION );
}
}
+
+void
+_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean mode )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ if (tnl->LoopbackDListCassettes != mode) {
+ tnl->LoopbackDListCassettes = mode;
+ }
+}
diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h
index 54f13e4649..226b877d85 100644
--- a/src/mesa/tnl/t_context.h
+++ b/src/mesa/tnl/t_context.h
@@ -1,4 +1,4 @@
-/* $Id: t_context.h,v 1.27 2001/06/01 16:29:18 brianp Exp $ */
+/* $Id: t_context.h,v 1.28 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
@@ -524,6 +524,7 @@ typedef struct {
/* Probably need a better configuration mechanism:
*/
GLboolean NeedProjCoords;
+ GLboolean LoopbackDListCassettes;
/* Derived state and storage for _tnl_eval_vb:
*/
diff --git a/src/mesa/tnl/t_imm_api.c b/src/mesa/tnl/t_imm_api.c
index 2a55e0ef63..9c4894ada7 100644
--- a/src/mesa/tnl/t_imm_api.c
+++ b/src/mesa/tnl/t_imm_api.c
@@ -1,4 +1,4 @@
-/* $Id: t_imm_api.c,v 1.14 2001/05/11 15:53:06 keithw Exp $ */
+/* $Id: t_imm_api.c,v 1.15 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
@@ -294,7 +294,9 @@ _tnl_end( GLcontext *ctx )
IM->Flag[count] |= VERT_END;
IM->Primitive[last] |= PRIM_END;
IM->PrimitiveLength[last] = count - last;
- IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END;
+ IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; /* removes PRIM_BEGIN
+ * flag if length == 0
+ */
IM->LastPrimitive = count;
if (IM->FlushElt == FLUSH_ELT_EAGER) {
diff --git a/src/mesa/tnl/t_imm_dlist.c b/src/mesa/tnl/t_imm_dlist.c
index c9d375831e..722d67b143 100644
--- a/src/mesa/tnl/t_imm_dlist.c
+++ b/src/mesa/tnl/t_imm_dlist.c
@@ -1,4 +1,4 @@
-/* $Id: t_imm_dlist.c,v 1.19 2001/05/14 09:00:51 keithw Exp $ */
+/* $Id: t_imm_dlist.c,v 1.20 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
@@ -63,6 +63,7 @@ typedef struct {
} TNLvertexcassette;
static void execute_compiled_cassette( GLcontext *ctx, void *data );
+static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM );
/* Insert the active immediate struct onto the display list currently
@@ -143,6 +144,93 @@ _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM )
}
+static void fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ /* Can potentially overwrite primitive details - need to save the
+ * first slot:
+ */
+ tnl->DlistPrimitive = IM->Primitive[IM->Start];
+ tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
+ tnl->DlistLastPrimitive = IM->LastPrimitive;
+
+ /* The first primitive may be different from what was recorded in
+ * the immediate struct. Consider an immediate that starts with a
+ * glBegin, compiled in a display list, which is called from within
+ * an existing Begin/End object.
+ */
+ if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
+ GLuint i;
+
+ if (IM->BeginState & VERT_ERROR_1)
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
+
+ for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
+ if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB))
+ break;
+
+ /* Would like to just ignore vertices upto this point. Can't
+ * set copystart because it might skip materials?
+ */
+ ASSERT(IM->Start == IM->CopyStart);
+ if (i > IM->CopyStart) {
+ IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
+ IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
+ if (IM->Flag[i] & VERT_END_VB) {
+ IM->Primitive[IM->CopyStart] |= PRIM_LAST;
+ IM->LastPrimitive = IM->CopyStart;
+ }
+ }
+ } else {
+ GLuint i;
+
+ if (IM->BeginState & VERT_ERROR_0)
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
+
+ if (IM->CopyStart == IM->Start &&
+ IM->Flag[IM->Start] & (VERT_END|VERT_END_VB))
+ {
+ }
+ else
+ {
+ IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
+ if (tnl->ExecParity)
+ IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
+
+ /* one of these should be true, else we'll be in an infinite loop
+ */
+ ASSERT(IM->PrimitiveLength[IM->Start] > 0 ||
+ IM->Flag[IM->Start] & (VERT_END|VERT_END_VB));
+
+ for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
+ if (IM->Flag[i] & (VERT_END|VERT_END_VB)) {
+ IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
+ if (IM->Flag[i] & VERT_END_VB) {
+ IM->Primitive[IM->CopyStart] |= PRIM_LAST;
+ IM->LastPrimitive = IM->CopyStart;
+ }
+ if (IM->Flag[i] & VERT_END) {
+ IM->Primitive[IM->CopyStart] |= PRIM_END;
+ }
+ break;
+ }
+ }
+ }
+}
+
+/* Undo any changes potentially made to the immediate in the range
+ * IM->Start..IM->Count above.
+ */
+static void restore_compiled_primitives( GLcontext *ctx, struct immediate *IM )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ IM->Primitive[IM->Start] = tnl->DlistPrimitive;
+ IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
+}
+
+
+
static void
execute_compiled_cassette( GLcontext *ctx, void *data )
{
@@ -152,12 +240,6 @@ execute_compiled_cassette( GLcontext *ctx, void *data )
/* fprintf(stderr, "%s\n", __FUNCTION__); */
- if (ctx->NewState)
- _mesa_update_state(ctx);
-
- if (tnl->pipeline.build_state_changes)
- _tnl_validate_pipeline( ctx );
-
IM->Start = node->Start;
IM->CopyStart = node->Start;
IM->Count = node->Count;
@@ -183,11 +265,10 @@ execute_compiled_cassette( GLcontext *ctx, void *data )
_tnl_print_vert_flags("orflag", IM->OrFlag);
}
- if (IM->Count == IM->Start) {
- _tnl_copy_to_current( ctx, IM, IM->OrFlag );
- return;
- }
+ /* Need to respect 'HardBeginEnd' even if the commands are looped
+ * back to a driver tnl module.
+ */
if (IM->SavedBeginState) {
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
tnl->ReplayHardBeginEnd = 1;
@@ -202,10 +283,35 @@ execute_compiled_cassette( GLcontext *ctx, void *data )
}
}
- _tnl_fixup_compiled_cassette( ctx, IM );
- _tnl_get_exec_copy_verts( ctx, IM );
- _tnl_run_cassette( ctx, IM );
- _tnl_restore_compiled_cassette( ctx, IM );
+ if (tnl->LoopbackDListCassettes) {
+ fixup_compiled_primitives( ctx, IM );
+ loopback_compiled_cassette( ctx, IM );
+ restore_compiled_primitives( ctx, IM );
+ }
+ else if (IM->Count == IM->Start) {
+ _tnl_copy_to_current( ctx, IM, IM->OrFlag );
+ }
+ else {
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (tnl->pipeline.build_state_changes)
+ _tnl_validate_pipeline( ctx );
+
+ _tnl_fixup_compiled_cassette( ctx, IM );
+ fixup_compiled_primitives( ctx, IM );
+
+ if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
+ ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+ else
+ ctx->Driver.CurrentExecPrimitive =
+ IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
+
+ _tnl_get_exec_copy_verts( ctx, IM );
+ _tnl_run_cassette( ctx, IM );
+
+ restore_compiled_primitives( ctx, IM );
+ }
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
tnl->ReplayHardBeginEnd = 0;
@@ -322,3 +428,162 @@ _tnl_dlist_init( GLcontext *ctx )
destroy_compiled_cassette,
print_compiled_cassette );
}
+
+
+static void emit_material( struct gl_material *src, GLuint bitmask )
+{
+ if (bitmask & FRONT_EMISSION_BIT)
+ glMaterialfv( GL_FRONT, GL_EMISSION, src[0].Emission );
+
+ if (bitmask & BACK_EMISSION_BIT)
+ glMaterialfv( GL_BACK, GL_EMISSION, src[1].Emission );
+
+ if (bitmask & FRONT_AMBIENT_BIT)
+ glMaterialfv( GL_FRONT, GL_AMBIENT, src[0].Ambient );
+
+ if (bitmask & BACK_AMBIENT_BIT)
+ glMaterialfv( GL_BACK, GL_AMBIENT, src[1].Ambient );
+
+ if (bitmask & FRONT_DIFFUSE_BIT)
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, src[0].Diffuse );
+
+ if (bitmask & BACK_DIFFUSE_BIT)
+ glMaterialfv( GL_BACK, GL_DIFFUSE, src[1].Diffuse );
+
+ if (bitmask & FRONT_SPECULAR_BIT)
+ glMaterialfv( GL_FRONT, GL_SPECULAR, src[0].Specular );
+
+ if (bitmask & BACK_SPECULAR_BIT)
+ glMaterialfv( GL_BACK, GL_SPECULAR, src[1].Specular );
+
+ if (bitmask & FRONT_SHININESS_BIT)
+ glMaterialfv( GL_FRONT, GL_SHININESS, &src[0].Shininess );
+
+ if (bitmask & BACK_SHININESS_BIT)
+ glMaterialfv( GL_BACK, GL_SHININESS, &src[1].Shininess );
+
+ if (bitmask & FRONT_INDEXES_BIT) {
+ GLfloat ind[3];
+ ind[0] = src[0].AmbientIndex;
+ ind[1] = src[0].DiffuseIndex;
+ ind[2] = src[0].SpecularIndex;
+ glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, ind );
+ }
+
+ if (bitmask & BACK_INDEXES_BIT) {
+ GLfloat ind[3];
+ ind[0] = src[1].AmbientIndex;
+ ind[1] = src[1].DiffuseIndex;
+ ind[2] = src[1].SpecularIndex;
+ glMaterialfv( GL_BACK, GL_COLOR_INDEXES, ind );
+ }
+}
+
+
+/* Low-performance helper function to allow driver-supplied tnl
+ * modules to process tnl display lists. This is primarily supplied
+ * to avoid fallbacks if CallList is invoked inside a Begin/End pair.
+ * For higher performance, drivers should fallback to tnl (if outside
+ * begin/end), or (for tnl hardware) implement their own display list
+ * mechanism.
+ */
+static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM )
+{
+ GLuint i;
+ GLuint *flags = IM->Flag;
+ GLuint orflag = IM->OrFlag;
+ GLuint j;
+ void (*vertex)( const GLfloat * );
+ void (*texcoordfv[MAX_TEXTURE_UNITS])( GLuint, const GLfloat * );
+ GLuint maxtex = 0;
+ GLuint p, length, prim = 0;
+
+ if (orflag & VERT_OBJ_234)
+ vertex = glVertex4fv;
+ else
+ vertex = glVertex3fv;
+
+ if (orflag & VERT_TEX_ANY) {
+ for (j = 0 ; j < ctx->Const.MaxTextureUnits ; j++) {
+ if (orflag & VERT_TEX(j)) {
+ maxtex = j+1;
+ if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j))
+ texcoordfv[j] = glMultiTexCoord4fvARB;
+ else if (IM->TexSize & TEX_SIZE_3(j))
+ texcoordfv[j] = glMultiTexCoord3fvARB;
+ else
+ texcoordfv[j] = glMultiTexCoord2fvARB;
+ }
+ }
+ }
+
+ for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length)
+ {
+ prim = IM->Primitive[p];
+ length= IM->PrimitiveLength[p];
+ ASSERT(length || (prim & PRIM_LAST));
+ ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1);
+
+ if (prim & PRIM_BEGIN) {
+/* fprintf(stderr, "begin %s\n", _mesa_prim_name[prim&PRIM_MODE_MASK]); */
+ glBegin(prim & PRIM_MODE_MASK);
+ }
+
+ for ( i = p ; i <= p+length ; i++) {
+ if (flags[i] & VERT_TEX_ANY) {
+ GLuint k;
+ for (k = 0 ; k < maxtex ; k++) {
+ if (flags[i] & VERT_TEX(k)) {
+ texcoordfv[k]( GL_TEXTURE0_ARB + k, IM->TexCoord[k][i] );
+ }
+ }
+ }
+
+ if (flags[i] & VERT_NORM) {
+/* fprintf(stderr, "normal %d: %f %f %f\n", i, */
+/* IM->Normal[i][0], IM->Normal[i][1], IM->Normal[i][2]); */
+ glNormal3fv(IM->Normal[i]);
+ }
+
+ if (flags[i] & VERT_RGBA) {
+/* fprintf(stderr, "color %d: %f %f %f\n", i, */
+/* IM->Color[i][0], IM->Color[i][1], IM->Color[i][2]); */
+ glColor4fv( IM->Color[i] );
+ }
+
+ if (flags[i] & VERT_SPEC_RGB)
+ glSecondaryColor3fvEXT( IM->SecondaryColor[i] );
+
+ if (flags[i] & VERT_FOG_COORD)
+ glFogCoordfEXT( IM->FogCoord[i] );
+
+ if (flags[i] & VERT_INDEX)
+ glIndexi( IM->Index[i] );
+
+ if (flags[i] & VERT_EDGE)
+ glEdgeFlag( IM->EdgeFlag[i] );
+
+ if (flags[i] & VERT_MATERIAL)
+ emit_material( IM->Material[i], IM->MaterialMask[i] );
+
+ if (flags[i]&VERT_OBJ_234) {
+/* fprintf(stderr, "vertex %d: %f %f %f\n", i, */
+/* IM->Obj[i][0], IM->Obj[i][1], IM->Obj[i][2]); */
+ vertex( IM->Obj[i] );
+ }
+ else if (flags[i] & VERT_EVAL_C1)
+ glEvalCoord1f(IM->Obj[i][0]);
+ else if (flags[i] & VERT_EVAL_P1)
+ glEvalPoint1(IM->Obj[i][0]);
+ else if (flags[i] & VERT_EVAL_C2)
+ glEvalCoord2f( IM->Obj[i][0], IM->Obj[i][1]);
+ else if (flags[i] & VERT_EVAL_P2)
+ glEvalPoint2( IM->Obj[i][0], IM->Obj[i][1]);
+ }
+
+ if (prim & PRIM_END) {
+/* fprintf(stderr, "end\n"); */
+ glEnd();
+ }
+ }
+}
diff --git a/src/mesa/tnl/t_imm_fixup.c b/src/mesa/tnl/t_imm_fixup.c
index 126aba1006..fdfeff566a 100644
--- a/src/mesa/tnl/t_imm_fixup.c
+++ b/src/mesa/tnl/t_imm_fixup.c
@@ -1,4 +1,4 @@
-/* $Id: t_imm_fixup.c,v 1.19 2001/05/16 09:28:32 keithw Exp $ */
+/* $Id: t_imm_fixup.c,v 1.20 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
@@ -592,93 +592,6 @@ void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
} while (vulnerable);
}
-
- /* Can potentially overwrite primitive details - need to save the
- * first slot:
- */
- tnl->DlistPrimitive = IM->Primitive[IM->Start];
- tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
- tnl->DlistLastPrimitive = IM->LastPrimitive;
-
- /* The first primitive may be different from what was recorded in
- * the immediate struct. Consider an immediate that starts with a
- * glBegin, compiled in a display list, which is called from within
- * an existing Begin/End object.
- */
- if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
- GLuint i;
-
- if (IM->BeginState & VERT_ERROR_1)
- _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
-
- for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
- if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB))
- break;
-
- /* Would like to just ignore vertices upto this point. Can't
- * set copystart because it might skip materials?
- */
- ASSERT(IM->Start == IM->CopyStart);
- if (i > IM->CopyStart) {
- IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
- IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
- if (IM->Flag[i] & VERT_END_VB) {
- IM->Primitive[IM->CopyStart] |= PRIM_LAST;
- IM->LastPrimitive = IM->CopyStart;
- }
- }
- } else {
- GLuint i;
-
- if (IM->BeginState & VERT_ERROR_0)
- _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
-
- if (IM->CopyStart == IM->Start &&
- IM->Flag[IM->Start] & (VERT_END|VERT_END_VB))
- {
- }
- else
- {
- IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
- if (tnl->ExecParity)
- IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
-
- /* one of these should be true, else we'll be in an infinite loop
- */
- ASSERT(IM->PrimitiveLength[IM->Start] > 0 ||
- IM->Flag[IM->Start] & (VERT_END|VERT_END_VB));
-
- for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
- if (IM->Flag[i] & (VERT_END|VERT_END_VB)) {
- IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
- if (IM->Flag[i] & VERT_END_VB) {
- IM->Primitive[IM->CopyStart] |= PRIM_LAST;
- IM->LastPrimitive = IM->CopyStart;
- }
- if (IM->Flag[i] & VERT_END) {
- IM->Primitive[IM->CopyStart] |= PRIM_END;
- }
- break;
- }
- }
- }
-
- if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
- ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
- else
- ctx->Driver.CurrentExecPrimitive =
- IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
-}
-
-
-/* Undo any changes potentially made to the immediate in the range
- * IM->Start..IM->Count above.
- */
-void _tnl_restore_compiled_cassette( GLcontext *ctx, struct immediate *IM )
-{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- IM->Primitive[IM->Start] = tnl->DlistPrimitive;
- IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
}
diff --git a/src/mesa/tnl/t_imm_fixup.h b/src/mesa/tnl/t_imm_fixup.h
index 5ca68b297a..806933aa68 100644
--- a/src/mesa/tnl/t_imm_fixup.h
+++ b/src/mesa/tnl/t_imm_fixup.h
@@ -1,4 +1,4 @@
-/* $Id: t_imm_fixup.h,v 1.5 2001/04/30 21:08:52 keithw Exp $ */
+/* $Id: t_imm_fixup.h,v 1.6 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
@@ -51,9 +51,6 @@ extern void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM );
extern void _tnl_fixup_compiled_cassette( GLcontext *ctx,
struct immediate *IM );
-extern void _tnl_restore_compiled_cassette( GLcontext *ctx,
- struct immediate *IM );
-
extern void _tnl_copy_immediate_vertices( GLcontext *ctx,
struct immediate *IM );
diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h
index 9ca530797e..413864aba1 100644
--- a/src/mesa/tnl/tnl.h
+++ b/src/mesa/tnl/tnl.h
@@ -1,4 +1,4 @@
-/* $Id: tnl.h,v 1.6 2001/03/12 00:48:44 gareth Exp $ */
+/* $Id: tnl.h,v 1.7 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
@@ -64,4 +64,7 @@ _tnl_wakeup_save_exec( GLcontext *ctx );
extern void
_tnl_need_projected_coords( GLcontext *ctx, GLboolean flag );
+extern void
+_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean flag );
+
#endif