summaryrefslogtreecommitdiff
path: root/src/mesa/tnl/t_imm_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/tnl/t_imm_api.c')
-rw-r--r--src/mesa/tnl/t_imm_api.c1398
1 files changed, 1398 insertions, 0 deletions
diff --git a/src/mesa/tnl/t_imm_api.c b/src/mesa/tnl/t_imm_api.c
new file mode 100644
index 0000000000..6224bff3cb
--- /dev/null
+++ b/src/mesa/tnl/t_imm_api.c
@@ -0,0 +1,1398 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.3
+ *
+ * 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.
+ *
+ * Author:
+ * Keith Whitwell <keith@precisioninsight.com>
+ */
+
+
+
+#include "glheader.h"
+#include "context.h"
+#include "dlist.h"
+#include "enums.h"
+#include "light.h"
+#include "mem.h"
+#include "state.h"
+#include "colormac.h"
+#include "macros.h"
+
+#include "t_context.h"
+#include "t_imm_api.h"
+#include "t_imm_elt.h"
+#include "t_imm_exec.h"
+#include "t_imm_dlist.h"
+
+
+/* A cassette is full or flushed on a statechange.
+ */
+void _tnl_flush_immediate( struct immediate *IM )
+{
+ GLcontext *ctx = IM->backref;
+
+ if (ctx->CompileFlag)
+ _tnl_compile_cassette( ctx, IM );
+ else
+ _tnl_execute_cassette( ctx, IM );
+}
+
+
+void _tnl_flush_vertices( GLcontext *ctx, GLuint flags )
+{
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+
+ if (IM->Flag[IM->Start])
+ if ((flags & FLUSH_UPDATE_CURRENT) || IM->Count > IM->Start)
+ _tnl_flush_immediate( IM );
+}
+
+
+void
+_tnl_begin( GLcontext *ctx, GLenum p )
+{
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+ GLuint inflags, state;
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glBegin(IM %d) %s\n", IM->id, gl_lookup_enum_by_nr(p));
+
+ if (ctx->NewState)
+ gl_update_state(ctx);
+
+ /* if only a very few slots left, might as well flush now
+ */
+ if (IM->Count > IMM_MAXDATA-8) {
+ _tnl_flush_immediate( IM );
+ IM = TNL_CURRENT_IM(ctx);
+ }
+
+ /* Check for and flush buffered vertices from internal operations.
+ */
+ if (IM->SavedBeginState) {
+ _tnl_flush_immediate( IM );
+ IM = TNL_CURRENT_IM(ctx);
+ IM->BeginState = IM->SavedBeginState;
+ IM->SavedBeginState = 0;
+ }
+
+ state = IM->BeginState;
+ inflags = state & (VERT_BEGIN_0|VERT_BEGIN_1);
+ state |= inflags << 2; /* set error conditions */
+
+ if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
+ {
+ GLuint count = IM->Count;
+ GLuint last = IM->LastPrimitive;
+
+ ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
+
+ state |= (VERT_BEGIN_0|VERT_BEGIN_1);
+ IM->Flag[count] |= VERT_BEGIN;
+ IM->Primitive[IM->LastPrimitive] &= ~PRIM_LAST;
+ IM->Primitive[count] = p | PRIM_BEGIN | PRIM_LAST;
+ IM->PrimitiveLength[IM->LastPrimitive] = count - IM->LastPrimitive;
+ IM->LastPrimitive = count;
+
+ /* Not quite right. Need to use the fallback '_aa_ArrayElement'
+ * when not known to be inside begin/end and arrays are unlocked.
+ */
+ if (IM->FlushElt) {
+ _tnl_translate_array_elts( ctx, IM, last, count );
+ IM->FlushElt = 0;
+ }
+ }
+
+ ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ IM->BeginState = state;
+}
+
+
+
+static void
+_tnl_Begin( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (mode > GL_POLYGON) {
+ _mesa_compile_error( ctx, GL_INVALID_ENUM, "glBegin" );
+ return;
+ }
+
+ _tnl_begin(ctx, mode);
+
+ /* If compiling update SavePrimitive now.
+ *
+ * In compile_and_exec mode, exec_primitive will be updated when
+ * the cassette is finished.
+ *
+ * If not compiling, update exec_primitive now.
+ */
+ if (ctx->CompileFlag) {
+ if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
+ ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
+ else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
+ ctx->Driver.CurrentSavePrimitive = mode;
+ }
+ else if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END)
+ ctx->Driver.CurrentExecPrimitive = mode;
+}
+
+
+GLboolean
+_tnl_hard_begin( GLcontext *ctx, GLenum p )
+{
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+ GLuint count, last;
+
+ if (ctx->NewState)
+ gl_update_state(ctx);
+
+ /* If not compiling, treat as a normal begin().
+ */
+ if (!ctx->CompileFlag) {
+ _tnl_begin( ctx, p );
+ return GL_TRUE;
+ }
+
+ if (IM->Count > IMM_MAXDATA-8) {
+ _tnl_flush_immediate( IM );
+ IM = TNL_CURRENT_IM(ctx);
+ }
+
+ switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) {
+ case VERT_BEGIN_0|VERT_BEGIN_1:
+ /* In this case we know for sure that the list is going to be
+ * inside a begin/end object at this point when run. Rather
+ * than saving the redundant data, compile in an error and
+ * return.
+ */
+ IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0);
+ return GL_FALSE;
+
+ case VERT_BEGIN_0:
+ case VERT_BEGIN_1:
+ /* This is a normal (non-hard) immediate, in an unknown
+ * begin/end state. Assert it is empty and conviert it to a
+ * 'hard' one.
+ */
+ ASSERT (IM->SavedBeginState == 0);
+
+/* ASSERT (ctx->Driver.CurrentSavePrimitive >= GL_POLYGON+1); */
+
+ /* Push current beginstate, to be restored later. Don't worry
+ * about raising errors.
+ */
+ IM->SavedBeginState = IM->BeginState;
+
+ /* FALLTHROUGH */
+ case 0:
+
+ IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
+
+
+ count = IM->Count;
+ last = IM->LastPrimitive;
+
+ ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
+
+ IM->Flag[count] |= VERT_BEGIN;
+ IM->Primitive[last] &= ~PRIM_LAST;
+ IM->Primitive[count] = p | PRIM_BEGIN | PRIM_LAST;
+ IM->PrimitiveLength[last] = count - last;
+ IM->LastPrimitive = count;
+
+ ASSERT (!IM->FlushElt);
+
+ /* This is necessary as this immediate will not be flushed in
+ * _tnl_end() -- we leave it active, hoping to pick up more
+ * vertices before the next state change.
+ */
+ ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ return GL_TRUE;
+
+ default:
+ ASSERT (0);
+ return GL_TRUE;
+ }
+}
+
+/* Note the continuation of a partially completed primitive. For
+ * driver t&l fallbacks between begin/end primitives. Has basically
+ * the same effects as a primitive wrapping onto a second immediate
+ * struct.
+ *
+ * ==> Can actually call this from _tnl_wakeup_exec, taking mode from
+ * ctx->Driver.CurrentExecPrimitive.
+ */
+#if 0
+void _tnl_fallback_begin( GLcontext *ctx, GLenum mode )
+{
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+ ASSERT( IM->Count == IM->Start );
+ ASSERT( IM->Flag[IM->Start] == 0 );
+ ASSERT( mode < GL_POLYGON+1 );
+ _tnl_begin( ctx, mode );
+ IM->Primitive[IM->Start] &= ~PRIM_BEGIN;
+}
+#endif
+
+
+/* Both streams now outside begin/end.
+ *
+ * Leave SavedBeginState untouched -- attempt to gather several
+ * rects/arrays together in a single immediate struct.
+ */
+void
+_tnl_end( GLcontext *ctx )
+{
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+ GLuint state = IM->BeginState;
+ GLuint inflags = (~state) & (VERT_BEGIN_0|VERT_BEGIN_1);
+
+ state |= inflags << 2; /* errors */
+
+ if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
+ {
+ GLuint count = IM->Count;
+ GLuint last = IM->LastPrimitive;
+
+ ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
+
+ state &= ~(VERT_BEGIN_0|VERT_BEGIN_1); /* update state */
+ IM->Flag[count] |= VERT_END;
+ IM->Primitive[last] |= PRIM_END;
+ IM->Primitive[last] &= ~PRIM_LAST;
+ IM->PrimitiveLength[last] = count - last;
+ IM->Primitive[count] = (GL_POLYGON+1) | PRIM_LAST;
+ IM->LastPrimitive = count;
+
+ if (IM->FlushElt) {
+ _tnl_translate_array_elts( ctx, IM, last, count );
+ IM->FlushElt = 0;
+ }
+
+ ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ }
+
+ IM->BeginState = state;
+
+ /* You can set this flag to get the old 'flush_vb on glEnd()'
+ * behaviour.
+ */
+ if ((MESA_DEBUG_FLAGS&DEBUG_ALWAYS_FLUSH))
+ _tnl_flush_immediate( IM );
+}
+
+static void
+_tnl_End(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _tnl_end( ctx );
+
+ /* Need to keep save primitive uptodate in COMPILE and
+ * COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
+ * otherwise.
+ */
+ if (ctx->CompileFlag)
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ else
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+
+
+}
+
+
+#define COLOR( IM, r, g, b, a ) \
+{ \
+ GLuint count = IM->Count; \
+ IM->Flag[count] |= VERT_RGBA; \
+ IM->Color[count][0] = r; \
+ IM->Color[count][1] = g; \
+ IM->Color[count][2] = b; \
+ IM->Color[count][3] = a; \
+}
+
+#define COLORV( IM, v ) \
+{ \
+ GLuint count = IM->Count; \
+ IM->Flag[count] |= VERT_RGBA; \
+ COPY_CHAN4(IM->Color[count], v); \
+}
+
+
+static void
+_tnl_Color3f( GLfloat red, GLfloat green, GLfloat blue )
+{
+#if CHAN_BITS == 8
+ GLubyte col[4];
+ GET_IMMEDIATE;
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[0], red);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[1], green);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[2], blue);
+ col[3] = CHAN_MAX;
+ COLORV( IM, col );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UNCLAMPED_FLOAT_TO_CHAN(red),
+ UNCLAMPED_FLOAT_TO_CHAN(green),
+ UNCLAMPED_FLOAT_TO_CHAN(blue),
+ CHAN_MAX);
+#endif
+}
+
+
+static void
+_tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue )
+{
+#if CHAN_BITS == 8
+ GET_IMMEDIATE;
+ COLOR( IM, red, green, blue, CHAN_MAX );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UBYTE_TO_CHAN(red),
+ UBYTE_TO_CHAN(green),
+ UBYTE_TO_CHAN(blue),
+ CHAN_MAX);
+#endif
+}
+
+
+
+
+static void
+_tnl_Color4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+{
+#if CHAN_BITS == 8
+ GLubyte col[4];
+ GET_IMMEDIATE;
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[0], red);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[1], green);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[2], blue);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[3], alpha);
+ COLORV( IM, col );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UNCLAMPED_FLOAT_TO_CHAN(red),
+ UNCLAMPED_FLOAT_TO_CHAN(green),
+ UNCLAMPED_FLOAT_TO_CHAN(blue),
+ UNCLAMPED_FLOAT_TO_CHAN(alpha));
+#endif
+}
+
+static void
+_tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
+{
+#if CHAN_BITS == 8
+ GET_IMMEDIATE;
+ COLOR( IM, red, green, blue, alpha );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UBYTE_TO_CHAN(red),
+ UBYTE_TO_CHAN(green),
+ UBYTE_TO_CHAN(blue),
+ UBYTE_TO_CHAN(alpha));
+#endif
+}
+
+
+static void
+_tnl_Color3fv( const GLfloat *v )
+{
+#if CHAN_BITS == 8
+ GLubyte col[4];
+ GET_IMMEDIATE;
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[0], v[0]);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[1], v[1]);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[2], v[2]);
+ col[3] = CHAN_MAX;
+ COLORV( IM, col );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UNCLAMPED_FLOAT_TO_CHAN(v[0]),
+ UNCLAMPED_FLOAT_TO_CHAN(v[1]),
+ UNCLAMPED_FLOAT_TO_CHAN(v[2]),
+ CHAN_MAX);
+
+#endif
+}
+
+
+
+static void
+_tnl_Color3ubv( const GLubyte *v )
+{
+#if CHAN_BITS == 8
+ GET_IMMEDIATE;
+ COLOR( IM, v[0], v[1], v[2], CHAN_MAX );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UBYTE_TO_CHAN(v[0]),
+ UBYTE_TO_CHAN(v[1]),
+ UBYTE_TO_CHAN(v[2]),
+ CHAN_MAX);
+#endif
+}
+
+static void
+_tnl_Color4fv( const GLfloat *v )
+{
+#if CHAN_BITS == 8
+ GLubyte col[4];
+ GET_IMMEDIATE;
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[0], v[0]);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[1], v[1]);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[2], v[2]);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[3], v[3]);
+ COLORV( IM, col );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UNCLAMPED_FLOAT_TO_CHAN(v[0]),
+ UNCLAMPED_FLOAT_TO_CHAN(v[1]),
+ UNCLAMPED_FLOAT_TO_CHAN(v[2]),
+ UNCLAMPED_FLOAT_TO_CHAN(v[3]));
+#endif
+}
+
+
+
+static void
+_tnl_Color4ubv( const GLubyte *v)
+{
+#if CHAN_BITS == 8
+ GET_IMMEDIATE;
+ COLORV( IM, v );
+#else
+ GET_IMMEDIATE;
+ COLOR(IM,
+ UBYTE_TO_CHAN(v[0]),
+ UBYTE_TO_CHAN(v[1]),
+ UBYTE_TO_CHAN(v[2]),
+ UBYTE_TO_CHAN(v[3]));
+#endif
+}
+
+
+
+
+#define SECONDARY_COLOR( IM, r, g, b ) \
+{ \
+ GLuint count = IM->Count; \
+ IM->Flag[count] |= VERT_SPEC_RGB; \
+ IM->SecondaryColor[count][0] = r; \
+ IM->SecondaryColor[count][1] = g; \
+ IM->SecondaryColor[count][2] = b; \
+}
+
+#define SECONDARY_COLORV( IM, v ) \
+{ \
+ GLuint count = IM->Count; \
+ IM->Flag[count] |= VERT_SPEC_RGB; \
+ IM->SecondaryColor[count][0] = v[0]; \
+ IM->SecondaryColor[count][1] = v[1]; \
+ IM->SecondaryColor[count][2] = v[2]; \
+}
+
+
+
+
+static void
+_tnl_SecondaryColor3fEXT( GLfloat red, GLfloat green, GLfloat blue )
+{
+#if CHAN_BITS == 8
+ GLubyte col[3];
+ GET_IMMEDIATE;
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[0], red);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[1], green);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[2], blue);
+ SECONDARY_COLORV( IM, col );
+#else
+ GET_IMMEDIATE;
+ SECONDARY_COLOR(IM,
+ UNCLAMPED_FLOAT_TO_CHAN(red),
+ UNCLAMPED_FLOAT_TO_CHAN(green),
+ UNCLAMPED_FLOAT_TO_CHAN(blue));
+#endif
+}
+
+
+
+static void
+_tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue )
+{
+#if CHAN_BITS == 8
+ GET_IMMEDIATE;
+ SECONDARY_COLOR( IM, red, green, blue );
+#else
+ GET_IMMEDIATE;
+ SECONDARY_COLOR(IM,
+ UBYTE_TO_CHAN(red),
+ UBYTE_TO_CHAN(green),
+ UBYTE_TO_CHAN(blue));
+#endif
+}
+
+
+
+
+static void
+_tnl_SecondaryColor3fvEXT( const GLfloat *v )
+{
+#if CHAN_BITS == 8
+ GLubyte col[3];
+ GET_IMMEDIATE;
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[0], v[0]);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[1], v[1]);
+ FLOAT_COLOR_TO_UBYTE_COLOR(col[2], v[2]);
+ SECONDARY_COLORV( IM, col );
+#else
+ GET_IMMEDIATE;
+ SECONDARY_COLOR(IM,
+ UNCLAMPED_FLOAT_TO_CHAN(v[0]),
+ UNCLAMPED_FLOAT_TO_CHAN(v[1]),
+ UNCLAMPED_FLOAT_TO_CHAN(v[2]));
+#endif
+}
+
+
+
+static void
+_tnl_SecondaryColor3ubvEXT( const GLubyte *v )
+{
+#if CHAN_BITS == 8
+ GET_IMMEDIATE;
+ SECONDARY_COLOR( IM, v[0], v[1], v[2] );
+#else
+ GET_IMMEDIATE;
+ SECONDARY_COLOR(IM,
+ UBYTE_TO_CHAN(v[0]),
+ UBYTE_TO_CHAN(v[1]),
+ UBYTE_TO_CHAN(v[2]));
+#endif
+}
+
+
+
+
+static void
+_tnl_EdgeFlag( GLboolean flag )
+{
+ GLuint count;
+ GET_IMMEDIATE;
+ count = IM->Count;
+ IM->EdgeFlag[count] = flag;
+ IM->Flag[count] |= VERT_EDGE;
+}
+
+
+static void
+_tnl_EdgeFlagv( const GLboolean *flag )
+{
+ GLuint count;
+ GET_IMMEDIATE;
+ count = IM->Count;
+ IM->EdgeFlag[count] = *flag;
+ IM->Flag[count] |= VERT_EDGE;
+}
+
+
+static void
+_tnl_FogCoordfEXT( GLfloat f )
+{
+ GLuint count;
+ GET_IMMEDIATE;
+ count = IM->Count;
+ IM->FogCoord[count] = f;
+ IM->Flag[count] |= VERT_FOG_COORD;
+}
+
+static void
+_tnl_FogCoordfvEXT( const GLfloat *v )
+{
+ GLuint count;
+ GET_IMMEDIATE;
+ count = IM->Count;
+ IM->FogCoord[count] = v[0];
+ IM->Flag[count] |= VERT_FOG_COORD;
+}
+
+
+static void
+_tnl_Indexi( GLint c )
+{
+ GLuint count;
+ GET_IMMEDIATE;
+ count = IM->Count;
+ IM->Index[count] = c;
+ IM->Flag[count] |= VERT_INDEX;
+}
+
+
+static void
+_tnl_Indexiv( const GLint *c )
+{
+ GLuint count;
+ GET_IMMEDIATE;
+ count = IM->Count;
+ IM->Index[count] = *c;
+ IM->Flag[count] |= VERT_INDEX;
+}
+
+
+#define NORMAL( x, y, z ) \
+{ \
+ GLuint count; \
+ GLfloat *normal; \
+ GET_IMMEDIATE; \
+ count = IM->Count; \
+ IM->Flag[count] |= VERT_NORM; \
+ normal = IM->Normal[count]; \
+ ASSIGN_3V(normal, x,y,z); \
+}
+
+#if defined(USE_IEEE)
+#define NORMALF( x, y, z ) \
+{ \
+ GLuint count; \
+ GLint *normal; \
+ GET_IMMEDIATE; \
+ count = IM->Count; \
+ IM->Flag[count] |= VERT_NORM; \
+ normal = (GLint *)IM->Normal[count]; \
+ ASSIGN_3V(normal, *(int*)&(x), *(int*)&(y), *(int*)&(z)); \
+}
+#else
+#define NORMALF NORMAL
+#endif
+
+static void
+_tnl_Normal3f( GLfloat nx, GLfloat ny, GLfloat nz )
+{
+ NORMALF(nx, ny, nz);
+}
+
+
+static void
+_tnl_Normal3fv( const GLfloat *v )
+{
+ NORMALF( v[0], v[1], v[2] );
+}
+
+
+
+#define TEXCOORD1(s) \
+{ \
+ GLuint count; \
+ GLfloat *tc; \
+ GET_IMMEDIATE; \
+ count = IM->Count; \
+ IM->Flag[count] |= VERT_TEX0; \
+ tc = IM->TexCoord0[count]; \
+ ASSIGN_4V(tc,s,0,0,1); \
+}
+
+#define TEXCOORD2(s,t) \
+{ \
+ GLuint count; \
+ GLfloat *tc; \
+ GET_IMMEDIATE; \
+ count = IM->Count; \
+ IM->Flag[count] |= VERT_TEX0; \
+ tc = IM->TexCoord0[count]; \
+ ASSIGN_4V(tc, s,t,0,1); \
+}
+
+#define TEXCOORD3(s,t,u) \
+{ \
+ GLuint count; \
+ GLfloat *tc; \
+ GET_IMMEDIATE; \
+ count = IM->Count; \
+ IM->Flag[count] |= VERT_TEX0; \
+ IM->TexSize |= TEX_0_SIZE_3; \
+ tc = IM->TexCoord0[count]; \
+ ASSIGN_4V(tc, s,t,u,1); \
+}
+
+#define TEXCOORD4(s,t,u,v) \
+{ \
+ GLuint count; \
+ GLfloat *tc; \
+ GET_IMMEDIATE; \
+ count = IM->Count; \
+ IM->Flag[count] |= VERT_TEX0; \
+ IM->TexSize |= TEX_0_SIZE_4; \
+ tc = IM->TexCoord0[count]; \
+ ASSIGN_4V(tc, s,t,u,v); \
+}
+
+#if defined(USE_IEEE)
+#define TEXCOORD2F(s,t) \
+{ \
+ GLuint count; \
+ GLint *tc; \
+ GET_IMMEDIATE; \
+ count = IM->Count; \
+ IM->Flag[count] |= VERT_TEX0; \
+ tc = (GLint *)IM->TexCoord0[count]; \
+ tc[0] = *(GLint *)&(s); \
+ tc[1] = *(GLint *)&(t); \
+ tc[2] = 0; \
+ tc[3] = IEEE_ONE; \
+}
+#else
+#define TEXCOORD2F TEXCOORD2
+#endif
+
+static void
+_tnl_TexCoord1f( GLfloat s )
+{
+ TEXCOORD1(s);
+}
+
+
+static void
+_tnl_TexCoord2f( GLfloat s, GLfloat t )
+{
+ TEXCOORD2F(s,t);
+}
+
+
+static void
+_tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r )
+{
+ TEXCOORD3(s,t,r);
+}
+
+static void
+_tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
+{
+ TEXCOORD4(s,t,r,q)
+}
+
+static void
+_tnl_TexCoord1fv( const GLfloat *v )
+{
+ TEXCOORD1(v[0]);
+}
+
+static void
+_tnl_TexCoord2fv( const GLfloat *v )
+{
+ TEXCOORD2F(v[0],v[1]);
+}
+
+static void
+_tnl_TexCoord3fv( const GLfloat *v )
+{
+ TEXCOORD3(v[0],v[1],v[2]);
+}
+
+static void
+_tnl_TexCoord4fv( const GLfloat *v )
+{
+ TEXCOORD4(v[0],v[1],v[2],v[3]);
+}
+
+
+
+/* KW: Run into bad problems in vertex copying if we don't fully pad
+ * the incoming vertices.
+ */
+#define VERTEX2(IM, x,y) \
+{ \
+ GLuint count = IM->Count++; \
+ GLfloat *dest = IM->Obj[count]; \
+ IM->Flag[count] |= VERT_OBJ; \
+ ASSIGN_4V(dest, x, y, 0, 1); \
+/* ASSERT(IM->Flag[IM->Count]==0); */\
+ if (count == IMM_MAXDATA - 1) \
+ _tnl_flush_immediate( IM ); \
+}
+
+#define VERTEX3(IM,x,y,z) \
+{ \
+ GLuint count = IM->Count++; \
+ GLfloat *dest = IM->Obj[count]; \
+ IM->Flag[count] |= VERT_OBJ_23; \
+ ASSIGN_4V(dest, x, y, z, 1); \
+/* ASSERT(IM->Flag[IM->Count]==0); */ \
+ if (count == IMM_MAXDATA - 1) \
+ _tnl_flush_immediate( IM ); \
+}
+
+#define VERTEX4(IM, x,y,z,w) \
+{ \
+ GLuint count = IM->Count++; \
+ GLfloat *dest = IM->Obj[count]; \
+ IM->Flag[count] |= VERT_OBJ_234; \
+ ASSIGN_4V(dest, x, y, z, w); \
+ if (count == IMM_MAXDATA - 1) \
+ _tnl_flush_immediate( IM ); \
+}
+
+#if defined(USE_IEEE)
+#define VERTEX2F(IM, x, y) \
+{ \
+ GLuint count = IM->Count++; \
+ GLint *dest = (GLint *)IM->Obj[count]; \
+ IM->Flag[count] |= VERT_OBJ; \
+ dest[0] = *(GLint *)&(x); \
+ dest[1] = *(GLint *)&(y); \
+ dest[2] = 0; \
+ dest[3] = IEEE_ONE; \
+/* ASSERT(IM->Flag[IM->Count]==0); */ \
+ if (count == IMM_MAXDATA - 1) \
+ _tnl_flush_immediate( IM ); \
+}
+#else
+#define VERTEX2F VERTEX2
+#endif
+
+#if defined(USE_IEEE)
+#define VERTEX3F(IM, x, y, z) \
+{ \
+ GLuint count = IM->Count++; \
+ GLint *dest = (GLint *)IM->Obj[count]; \
+ IM->Flag[count] |= VERT_OBJ_23; \
+ dest[0] = *(GLint *)&(x); \
+ dest[1] = *(GLint *)&(y); \
+ dest[2] = *(GLint *)&(z); \
+ dest[3] = IEEE_ONE; \
+/* ASSERT(IM->Flag[IM->Count]==0); */ \
+ if (count == IMM_MAXDATA - 1) \
+ _tnl_flush_immediate( IM ); \
+}
+#else
+#define VERTEX3F VERTEX3
+#endif
+
+#if defined(USE_IEEE)
+#define VERTEX4F(IM, x, y, z, w) \
+{ \
+ GLuint count = IM->Count++; \
+ GLint *dest = (GLint *)IM->Obj[count]; \
+ IM->Flag[count] |= VERT_OBJ_234; \
+ dest[0] = *(GLint *)&(x); \
+ dest[1] = *(GLint *)&(y); \
+ dest[2] = *(GLint *)&(z); \
+ dest[3] = *(GLint *)&(w); \
+ if (count == IMM_MAXDATA - 1) \
+ _tnl_flush_immediate( IM ); \
+}
+#else
+#define VERTEX4F VERTEX4
+#endif
+
+
+
+static void
+_tnl_Vertex2f( GLfloat x, GLfloat y )
+{
+ GET_IMMEDIATE;
+ VERTEX2F( IM, x, y );
+}
+
+static void
+_tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_IMMEDIATE;
+ VERTEX3F( IM, x, y, z );
+}
+static void
+_tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ GET_IMMEDIATE;
+ VERTEX4F( IM, x, y, z, w );
+}
+
+static void
+_tnl_Vertex2fv( const GLfloat *v )
+{
+ GET_IMMEDIATE;
+ VERTEX2F( IM, v[0], v[1] );
+}
+
+static void
+_tnl_Vertex3fv( const GLfloat *v )
+{
+ GET_IMMEDIATE;
+ VERTEX3F( IM, v[0], v[1], v[2] );
+}
+
+static void
+_tnl_Vertex4fv( const GLfloat *v )
+{
+ GET_IMMEDIATE;
+ VERTEX4F( IM, v[0], v[1], v[2], v[3] );
+}
+
+
+
+
+/*
+ * GL_ARB_multitexture
+ *
+ * Note: the multitexture spec says that specifying an invalid target
+ * has undefined results and does not have to generate an error. Just
+ * don't crash. We no-op on invalid targets.
+ */
+
+#define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
+
+#define MULTI_TEXCOORD1(target, s) \
+{ \
+ GET_IMMEDIATE; \
+ GLuint texunit = target - GL_TEXTURE0_ARB; \
+ if (texunit < IM->MaxTextureUnits) { \
+ GLuint count = IM->Count; \
+ GLfloat *tc = IM->TexCoord[texunit][count]; \
+ ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
+ IM->Flag[count] |= VERT_TEX(texunit); \
+ } \
+}
+
+#define MULTI_TEXCOORD2(target, s, t) \
+{ \
+ GET_IMMEDIATE; \
+ GLuint texunit = target - GL_TEXTURE0_ARB; \
+ if (texunit < IM->MaxTextureUnits) { \
+ GLuint count = IM->Count; \
+ GLfloat *tc = IM->TexCoord[texunit][count]; \
+ ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
+ IM->Flag[count] |= VERT_TEX(texunit); \
+ } \
+}
+
+#define MULTI_TEXCOORD3(target, s, t, u) \
+{ \
+ GET_IMMEDIATE; \
+ GLuint texunit = target - GL_TEXTURE0_ARB; \
+ if (texunit < IM->MaxTextureUnits) { \
+ GLuint count = IM->Count; \
+ GLfloat *tc = IM->TexCoord[texunit][count]; \
+ ASSIGN_4V(tc, s, t, u, 1.0F); \
+ IM->Flag[count] |= VERT_TEX(texunit); \
+ IM->TexSize |= TEX_SIZE_3(texunit); \
+ } \
+}
+
+#define MULTI_TEXCOORD4(target, s, t, u, v) \
+{ \
+ GET_IMMEDIATE; \
+ GLuint texunit = target - GL_TEXTURE0_ARB; \
+ if (texunit < IM->MaxTextureUnits) { \
+ GLuint count = IM->Count; \
+ GLfloat *tc = IM->TexCoord[texunit][count]; \
+ ASSIGN_4V(tc, s, t, u, v); \
+ IM->Flag[count] |= VERT_TEX(texunit); \
+ IM->TexSize |= TEX_SIZE_4(texunit); \
+ } \
+}
+
+#if defined(USE_IEEE)
+#define MULTI_TEXCOORD2F(target, s, t) \
+{ \
+ GET_IMMEDIATE; \
+ GLuint texunit = target - GL_TEXTURE0_ARB; \
+ if (texunit < IM->MaxTextureUnits) { \
+ GLuint count = IM->Count; \
+ GLint *tc = (GLint *)IM->TexCoord[texunit][count]; \
+ IM->Flag[count] |= VERT_TEX(texunit); \
+ tc[0] = *(int *)&(s); \
+ tc[1] = *(int *)&(t); \
+ tc[2] = 0; \
+ tc[3] = IEEE_ONE; \
+ } \
+}
+#else
+#define MULTI_TEXCOORD2F MULTI_TEXCOORD2
+#endif
+
+static void
+_tnl_MultiTexCoord1fARB(GLenum target, GLfloat s)
+{
+ MULTI_TEXCOORD1( target, s );
+}
+
+static void
+_tnl_MultiTexCoord1fvARB(GLenum target, const GLfloat *v)
+{
+ MULTI_TEXCOORD1( target, v[0] );
+}
+
+static void
+_tnl_MultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t)
+{
+ MULTI_TEXCOORD2F( target, s, t );
+}
+
+static void
+_tnl_MultiTexCoord2fvARB(GLenum target, const GLfloat *v)
+{
+ MULTI_TEXCOORD2F( target, v[0], v[1] );
+}
+
+static void
+_tnl_MultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r)
+{
+ MULTI_TEXCOORD3( target, s, t, r );
+}
+
+static void
+_tnl_MultiTexCoord3fvARB(GLenum target, const GLfloat *v)
+{
+ MULTI_TEXCOORD3( target, v[0], v[1], v[2] );
+}
+
+static void
+_tnl_MultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ MULTI_TEXCOORD4( target, s, t, r, q );
+}
+
+static void
+_tnl_MultiTexCoord4fvARB(GLenum target, const GLfloat *v)
+{
+ MULTI_TEXCOORD4( target, v[0], v[1], v[2], v[3] );
+}
+
+
+
+/* KW: Because the eval values don't become 'current', fixup will flow
+ * through these vertices, and then evaluation will write on top
+ * of the fixup results.
+ *
+ * Note: using Obj to hold eval coord data.
+ */
+#define EVALCOORD1(IM, x) \
+{ \
+ GLuint count = IM->Count++; \
+ IM->Flag[count] |= VERT_EVAL_C1; \
+ ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
+ if (count == IMM_MAXDATA-1) \
+ _tnl_flush_immediate( IM ); \
+}
+
+#define EVALCOORD2(IM, x, y) \
+{ \
+ GLuint count = IM->Count++; \
+ IM->Flag[count] |= VERT_EVAL_C2; \
+ ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
+ if (count == IMM_MAXDATA-1) \
+ _tnl_flush_immediate( IM ); \
+}
+
+#define EVALPOINT1(IM, x) \
+{ \
+ GLuint count = IM->Count++; \
+ IM->Flag[count] |= VERT_EVAL_P1; \
+ ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
+ if (count == IMM_MAXDATA-1) \
+ _tnl_flush_immediate( IM ); \
+}
+
+#define EVALPOINT2(IM, x, y) \
+{ \
+ GLuint count = IM->Count++; \
+ IM->Flag[count] |= VERT_EVAL_P2; \
+ ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
+ if (count == IMM_MAXDATA-1) \
+ _tnl_flush_immediate( IM ); \
+}
+
+static void
+_tnl_EvalCoord1f( GLfloat u )
+{
+ GET_IMMEDIATE;
+ EVALCOORD1( IM, u );
+}
+
+static void
+_tnl_EvalCoord1fv( const GLfloat *u )
+{
+ GET_IMMEDIATE;
+ EVALCOORD1( IM, (GLfloat) *u );
+}
+
+static void
+_tnl_EvalCoord2f( GLfloat u, GLfloat v )
+{
+ GET_IMMEDIATE;
+ EVALCOORD2( IM, u, v );
+}
+
+static void
+_tnl_EvalCoord2fv( const GLfloat *u )
+{
+ GET_IMMEDIATE;
+ EVALCOORD2( IM, u[0], u[1] );
+}
+
+
+static void
+_tnl_EvalPoint1( GLint i )
+{
+ GET_IMMEDIATE;
+ EVALPOINT1( IM, i );
+}
+
+
+static void
+_tnl_EvalPoint2( GLint i, GLint j )
+{
+ GET_IMMEDIATE;
+ EVALPOINT2( IM, i, j );
+}
+
+
+/* Need to use the default array-elt outside begin/end for strict
+ * conformance.
+ */
+#define ARRAY_ELT( IM, i ) \
+{ \
+ GLuint count = IM->Count; \
+ IM->Elt[count] = i; \
+ IM->Flag[count] &= IM->ArrayEltFlags; \
+ IM->Flag[count] |= VERT_ELT; \
+ IM->FlushElt |= IM->ArrayEltFlush; \
+ IM->Count += IM->ArrayEltIncr; \
+ if (IM->Count == IMM_MAXDATA) \
+ _tnl_flush_immediate( IM ); \
+}
+
+
+static void
+_tnl_ArrayElement( GLint i )
+{
+ GET_IMMEDIATE;
+ ARRAY_ELT( IM, i );
+}
+
+
+/* Internal functions. These are safe to use providing either:
+ *
+ * - It is determined that a display list is not being compiled, or
+ * if so that these commands won't be compiled into the list (see
+ * t_eval.c for an example).
+ *
+ * - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
+ * for a GL_TRUE return value. See _tnl_Rectf, below.
+ */
+void
+_tnl_eval_coord1f( GLcontext *CC, GLfloat u )
+{
+ struct immediate *i = TNL_CURRENT_IM(CC);
+ EVALCOORD1( i, u );
+}
+
+void
+_tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v )
+{
+ struct immediate *i = TNL_CURRENT_IM(CC);
+ EVALCOORD2( i, u, v );
+}
+
+void
+_tnl_array_element( GLcontext *CC, GLint i )
+{
+ struct immediate *im = TNL_CURRENT_IM(CC);
+ ARRAY_ELT( im, i );
+}
+
+void
+_tnl_vertex2f( GLcontext *ctx, GLfloat x, GLfloat y )
+{
+ struct immediate *im = TNL_CURRENT_IM(ctx);
+ VERTEX2( im, x, y );
+}
+
+
+
+
+
+/* Execute a glRectf() function. _tnl_hard_begin() ensures the check
+ * on outside_begin_end is executed even in compiled lists. These
+ * vertices can now participate in the same VB as regular ones, even
+ * in most display lists.
+ */
+static void
+_tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (_tnl_hard_begin( ctx, GL_QUADS )) {
+ _tnl_vertex2f( ctx, x1, y1 );
+ _tnl_vertex2f( ctx, x2, y1 );
+ _tnl_vertex2f( ctx, x2, y2 );
+ _tnl_vertex2f( ctx, x1, y2 );
+ _tnl_end( ctx );
+ }
+}
+
+static void
+_tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+ GLuint count = IM->Count;
+ struct gl_material *mat;
+ GLuint bitmask = gl_material_bitmask( ctx, face, pname, ~0, "Materialfv" );
+
+ if (bitmask == 0)
+ return;
+
+ if (!IM->Material) {
+ IM->Material = (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial) *
+ IMM_SIZE * 2 );
+ IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
+ }
+
+ if (!(IM->Flag[count] & VERT_MATERIAL)) {
+ IM->Flag[count] |= VERT_MATERIAL;
+ IM->MaterialMask[count] = 0;
+ }
+
+ IM->MaterialMask[count] |= bitmask;
+ mat = IM->Material[count];
+
+ if (bitmask & FRONT_AMBIENT_BIT) {
+ COPY_4FV( mat[0].Ambient, params );
+ }
+ if (bitmask & BACK_AMBIENT_BIT) {
+ COPY_4FV( mat[1].Ambient, params );
+ }
+ if (bitmask & FRONT_DIFFUSE_BIT) {
+ COPY_4FV( mat[0].Diffuse, params );
+ }
+ if (bitmask & BACK_DIFFUSE_BIT) {
+ COPY_4FV( mat[1].Diffuse, params );
+ }
+ if (bitmask & FRONT_SPECULAR_BIT) {
+ COPY_4FV( mat[0].Specular, params );
+ }
+ if (bitmask & BACK_SPECULAR_BIT) {
+ COPY_4FV( mat[1].Specular, params );
+ }
+ if (bitmask & FRONT_EMISSION_BIT) {
+ COPY_4FV( mat[0].Emission, params );
+ }
+ if (bitmask & BACK_EMISSION_BIT) {
+ COPY_4FV( mat[1].Emission, params );
+ }
+ if (bitmask & FRONT_SHININESS_BIT) {
+ GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
+ mat[0].Shininess = shininess;
+ }
+ if (bitmask & BACK_SHININESS_BIT) {
+ GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
+ mat[1].Shininess = shininess;
+ }
+ if (bitmask & FRONT_INDEXES_BIT) {
+ mat[0].AmbientIndex = params[0];
+ mat[0].DiffuseIndex = params[1];
+ mat[0].SpecularIndex = params[2];
+ }
+ if (bitmask & BACK_INDEXES_BIT) {
+ mat[1].AmbientIndex = params[0];
+ mat[1].DiffuseIndex = params[1];
+ mat[1].SpecularIndex = params[2];
+ }
+}
+
+void _tnl_imm_vtxfmt_init( GLcontext *ctx )
+{
+ GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
+
+ /* All begin/end operations are handled by this vertex format:
+ */
+ vfmt->ArrayElement = _tnl_ArrayElement;
+ vfmt->Begin = _tnl_Begin;
+ vfmt->Color3f = _tnl_Color3f;
+ vfmt->Color3fv = _tnl_Color3fv;
+ vfmt->Color3ub = _tnl_Color3ub;
+ vfmt->Color3ubv = _tnl_Color3ubv;
+ vfmt->Color4f = _tnl_Color4f;
+ vfmt->Color4fv = _tnl_Color4fv;
+ vfmt->Color4ub = _tnl_Color4ub;
+ vfmt->Color4ubv = _tnl_Color4ubv;
+ vfmt->EdgeFlag = _tnl_EdgeFlag;
+ vfmt->EdgeFlagv = _tnl_EdgeFlagv;
+ vfmt->End = _tnl_End;
+ vfmt->EvalCoord1f = _tnl_EvalCoord1f;
+ vfmt->EvalCoord1fv = _tnl_EvalCoord1fv;
+ vfmt->EvalCoord2f = _tnl_EvalCoord2f;
+ vfmt->EvalCoord2fv = _tnl_EvalCoord2fv;
+ vfmt->EvalPoint1 = _tnl_EvalPoint1;
+ vfmt->EvalPoint2 = _tnl_EvalPoint2;
+ vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
+ vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
+ vfmt->Indexi = _tnl_Indexi;
+ vfmt->Indexiv = _tnl_Indexiv;
+ vfmt->Materialfv = _tnl_Materialfv;
+ vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1fARB;
+ vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fvARB;
+ vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2fARB;
+ vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fvARB;
+ vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3fARB;
+ vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fvARB;
+ vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4fARB;
+ vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fvARB;
+ vfmt->Normal3f = _tnl_Normal3f;
+ vfmt->Normal3fv = _tnl_Normal3fv;
+ vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
+ vfmt->SecondaryColor3ubEXT = _tnl_SecondaryColor3ubEXT;
+ vfmt->SecondaryColor3ubvEXT = _tnl_SecondaryColor3ubvEXT;
+ vfmt->TexCoord1f = _tnl_TexCoord1f;
+ vfmt->TexCoord1fv = _tnl_TexCoord1fv;
+ vfmt->TexCoord2f = _tnl_TexCoord2f;
+ vfmt->TexCoord2fv = _tnl_TexCoord2fv;
+ vfmt->TexCoord3f = _tnl_TexCoord3f;
+ vfmt->TexCoord3fv = _tnl_TexCoord3fv;
+ vfmt->TexCoord4f = _tnl_TexCoord4f;
+ vfmt->TexCoord4fv = _tnl_TexCoord4fv;
+ vfmt->Vertex2f = _tnl_Vertex2f;
+ vfmt->Vertex2fv = _tnl_Vertex2fv;
+ vfmt->Vertex3f = _tnl_Vertex3f;
+ vfmt->Vertex3fv = _tnl_Vertex3fv;
+ vfmt->Vertex4f = _tnl_Vertex4f;
+ vfmt->Vertex4fv = _tnl_Vertex4fv;
+
+ /* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
+ */
+ vfmt->Rectf = _tnl_Rectf;
+
+ /* Just use the core function:
+ */
+ vfmt->CallList = _mesa_CallList;
+
+ vfmt->prefer_float_colors = GL_FALSE;
+}