new files
authorKeith Whitwell <keith@tungstengraphics.com>
Mon, 29 Mar 2004 14:01:56 +0000 (14:01 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Mon, 29 Mar 2004 14:01:56 +0000 (14:01 +0000)
src/mesa/tnl/t_vtx_generic.c [new file with mode: 0644]
src/mesa/tnl/t_vtx_x86.c [new file with mode: 0644]

diff --git a/src/mesa/tnl/t_vtx_generic.c b/src/mesa/tnl/t_vtx_generic.c
new file mode 100644 (file)
index 0000000..25dd07a
--- /dev/null
@@ -0,0 +1,459 @@
+/**************************************************************************
+
+Copyright 2004 Tungsten Graphics Inc., Cedar Park, Texas.
+
+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
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, 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 (including the next
+paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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 <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "vtxfmt.h"
+#include "dlist.h"
+#include "state.h"
+#include "light.h"
+#include "api_arrayelt.h"
+#include "api_noop.h"
+#include "t_vtx_api.h"
+
+
+/* Versions of all the entrypoints for situations where codegen isn't
+ * available.  
+ *
+ * Note: Only one size for each attribute may be active at once.
+ * Eg. if Color3f is installed/active, then Color4f may not be, even
+ * if the vertex actually contains 4 color coordinates.  This is
+ * because the 3f version won't otherwise set color[3] to 1.0 -- this
+ * is the job of the chooser function when switching between Color4f
+ * and Color3f.
+ */
+#define ATTRFV( ATTR, N )                              \
+static void attrib_##ATTR##_##N( const GLfloat *v )    \
+{                                                      \
+   GET_CURRENT_CONTEXT( ctx );                         \
+   TNLcontext *tnl = TNL_CONTEXT(ctx);                 \
+                                                       \
+   if ((ATTR) == 0) {                                  \
+      GLuint i;                                                \
+                                                       \
+      if (N>0) tnl->vtx.vbptr[0] = v[0];               \
+      if (N>1) tnl->vtx.vbptr[1] = v[1];               \
+      if (N>2) tnl->vtx.vbptr[2] = v[2];               \
+      if (N>3) tnl->vtx.vbptr[3] = v[3];               \
+                                                       \
+      for (i = N; i < tnl->vtx.vertex_size; i++)       \
+        tnl->vtx.vbptr[i] = tnl->vtx.vertex[i];        \
+                                                       \
+      tnl->vtx.vbptr += tnl->vtx.vertex_size;          \
+                                                       \
+      if (--tnl->vtx.counter == 0)                     \
+        _tnl_wrap_filled_vertex( ctx );                \
+   }                                                   \
+   else {                                              \
+      GLfloat *dest = tnl->vtx.attrptr[ATTR];          \
+      if (N>0) dest[0] = v[0];                         \
+      if (N>1) dest[1] = v[1];                         \
+      if (N>2) dest[2] = v[2];                         \
+      if (N>3) dest[3] = v[3];                         \
+   }                                                   \
+}
+
+#define INIT(TAB, ATTR)                                                \
+   TAB[ATTR][0] = attrib_##ATTR##_1;                           \
+   TAB[ATTR][1] = attrib_##ATTR##_2;                           \
+   TAB[ATTR][2] = attrib_##ATTR##_3;                           \
+   TAB[ATTR][3] = attrib_##ATTR##_4;
+
+
+#define ATTRS( ATTRIB )                                \
+   ATTRFV( ATTRIB, 1 )                         \
+   ATTRFV( ATTRIB, 2 )                         \
+   ATTRFV( ATTRIB, 3 )                         \
+   ATTRFV( ATTRIB, 4 )                 
+
+ATTRS( 0 )
+ATTRS( 1 )
+ATTRS( 2 )
+ATTRS( 3 )
+ATTRS( 4 )
+ATTRS( 5 )
+ATTRS( 6 )
+ATTRS( 7 )
+ATTRS( 8 )
+ATTRS( 9 )
+ATTRS( 10 )
+ATTRS( 11 )
+ATTRS( 12 )
+ATTRS( 13 )
+ATTRS( 14 )
+ATTRS( 15 )
+
+void _tnl_generic_attr_table_init( attrfv_func (*tab)[4] )
+{
+   INIT( tab, 0 );
+   INIT( tab, 1 );
+   INIT( tab, 2 );
+   INIT( tab, 3 );
+   INIT( tab, 4 );
+   INIT( tab, 5 );
+   INIT( tab, 6 );
+   INIT( tab, 7 );
+   INIT( tab, 8 );
+   INIT( tab, 9 );
+   INIT( tab, 10 );
+   INIT( tab, 11 );
+   INIT( tab, 12 );
+   INIT( tab, 13 );
+   INIT( tab, 14 );
+   INIT( tab, 15 );
+}
+
+/* These can be made efficient with codegen.  Further, by adding more
+ * logic to do_choose(), the double-dispatch for legacy entrypoints
+ * like glVertex3f() can be removed.
+ */
+#define DISPATCH_ATTRFV( ATTR, COUNT, P )      \
+do {                                           \
+   GET_CURRENT_CONTEXT( ctx );                         \
+   TNLcontext *tnl = TNL_CONTEXT(ctx);                 \
+   tnl->vtx.tabfv[ATTR][COUNT-1]( P );         \
+} while (0)
+
+#define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V )
+#define DISPATCH_ATTR2FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 2, V )
+#define DISPATCH_ATTR3FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 3, V )
+#define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V )
+
+#define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) )
+
+#define DISPATCH_ATTR2F( ATTR, S,T )           \
+do {                                           \
+   GLfloat v[2];                               \
+   v[0] = S; v[1] = T;                         \
+   DISPATCH_ATTR2FV( ATTR, v );                        \
+} while (0)
+#define DISPATCH_ATTR3F( ATTR, S,T,R )                 \
+do {                                           \
+   GLfloat v[3];                               \
+   v[0] = S; v[1] = T; v[2] = R;               \
+   DISPATCH_ATTR3FV( ATTR, v );                        \
+} while (0)
+#define DISPATCH_ATTR4F( ATTR, S,T,R,Q )       \
+do {                                           \
+   GLfloat v[4];                               \
+   v[0] = S; v[1] = T; v[2] = R; v[3] = Q;     \
+   DISPATCH_ATTR4FV( ATTR, v );                        \
+} while (0)
+
+
+static void GLAPIENTRY _tnl_Vertex2f( GLfloat x, GLfloat y )
+{
+   DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y );
+}
+
+static void GLAPIENTRY _tnl_Vertex2fv( const GLfloat *v )
+{
+   DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v );
+}
+
+static void GLAPIENTRY _tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z );
+}
+
+static void GLAPIENTRY _tnl_Vertex3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v );
+}
+
+static void GLAPIENTRY _tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, 
+                                     GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w );
+}
+
+static void GLAPIENTRY _tnl_Vertex4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v );
+}
+
+static void GLAPIENTRY _tnl_TexCoord1f( GLfloat x )
+{
+   DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x );
+}
+
+static void GLAPIENTRY _tnl_TexCoord1fv( const GLfloat *v )
+{
+   DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY _tnl_TexCoord2f( GLfloat x, GLfloat y )
+{
+   DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y );
+}
+
+static void GLAPIENTRY _tnl_TexCoord2fv( const GLfloat *v )
+{
+   DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY _tnl_TexCoord3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z );
+}
+
+static void GLAPIENTRY _tnl_TexCoord3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY _tnl_TexCoord4f( GLfloat x, GLfloat y, GLfloat z,
+                                       GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w );
+}
+
+static void GLAPIENTRY _tnl_TexCoord4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY _tnl_Normal3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z );
+}
+
+static void GLAPIENTRY _tnl_Normal3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v );
+}
+
+static void GLAPIENTRY _tnl_FogCoordfEXT( GLfloat x )
+{
+   DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x );
+}
+
+static void GLAPIENTRY _tnl_FogCoordfvEXT( const GLfloat *v )
+{
+   DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v );
+}
+
+static void GLAPIENTRY _tnl_Color3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z );
+}
+
+static void GLAPIENTRY _tnl_Color3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v );
+}
+
+static void GLAPIENTRY _tnl_Color4f( GLfloat x, GLfloat y, GLfloat z, 
+                                    GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_COLOR0, x, y, z, w );
+}
+
+static void GLAPIENTRY _tnl_Color4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_COLOR0, v );
+}
+
+static void GLAPIENTRY _tnl_SecondaryColor3fEXT( GLfloat x, GLfloat y, 
+                                                GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR1, x, y, z );
+}
+
+static void GLAPIENTRY _tnl_SecondaryColor3fvEXT( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR1, v );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord1f( GLenum target, GLfloat x  )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR1F( attr, x );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord1fv( GLenum target,
+                                             const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR1FV( attr, v );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord2f( GLenum target, GLfloat x, 
+                                            GLfloat y )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR2F( attr, x, y );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord2fv( GLenum target, 
+                                             const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR2FV( attr, v );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord3f( GLenum target, GLfloat x, 
+                                            GLfloat y, GLfloat z)
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR3F( attr, x, y, z );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord3fv( GLenum target, 
+                                             const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR3FV( attr, v );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord4f( GLenum target, GLfloat x, 
+                                            GLfloat y, GLfloat z,
+                                            GLfloat w )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR4F( attr, x, y, z, w );
+}
+
+static void GLAPIENTRY _tnl_MultiTexCoord4fv( GLenum target, 
+                                             const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR4FV( attr, v );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib1fNV( GLuint index, GLfloat x )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR1F( index, x );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib1fvNV( GLuint index, 
+                                              const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR1FV( index, v );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib2fNV( GLuint index, GLfloat x, 
+                                             GLfloat y )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR2F( index, x, y );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib2fvNV( GLuint index,
+                                              const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR2FV( index, v );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib3fNV( GLuint index, GLfloat x,
+                                             GLfloat y, GLfloat z )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR3F( index, x, y, z );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib3fvNV( GLuint index,
+                                              const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR3FV( index, v );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib4fNV( GLuint index, GLfloat x,
+                                             GLfloat y, GLfloat z,
+                                             GLfloat w )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR4F( index, x, y, z, w );
+}
+
+static void GLAPIENTRY _tnl_VertexAttrib4fvNV( GLuint index, 
+                                              const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
+   DISPATCH_ATTR4FV( index, v );
+}
+
+
+/* Install the generic versions of the 2nd level dispatch functions.
+ * There's currently no codegen alternative to these, though one is in
+ * the works.
+ */
+void _tnl_generic_exec_vtxfmt_init( GLcontext *ctx )
+{
+   GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt);
+
+   vfmt->Color3f = _tnl_Color3f;
+   vfmt->Color3fv = _tnl_Color3fv;
+   vfmt->Color4f = _tnl_Color4f;
+   vfmt->Color4fv = _tnl_Color4fv;
+   vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
+   vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
+   vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1f;
+   vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fv;
+   vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2f;
+   vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fv;
+   vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3f;
+   vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fv;
+   vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4f;
+   vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fv;
+   vfmt->Normal3f = _tnl_Normal3f;
+   vfmt->Normal3fv = _tnl_Normal3fv;
+   vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
+   vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
+   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;
+   vfmt->VertexAttrib1fNV = _tnl_VertexAttrib1fNV;
+   vfmt->VertexAttrib1fvNV = _tnl_VertexAttrib1fvNV;
+   vfmt->VertexAttrib2fNV = _tnl_VertexAttrib2fNV;
+   vfmt->VertexAttrib2fvNV = _tnl_VertexAttrib2fvNV;
+   vfmt->VertexAttrib3fNV = _tnl_VertexAttrib3fNV;
+   vfmt->VertexAttrib3fvNV = _tnl_VertexAttrib3fvNV;
+   vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV;
+   vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV;
+}
diff --git a/src/mesa/tnl/t_vtx_x86.c b/src/mesa/tnl/t_vtx_x86.c
new file mode 100644 (file)
index 0000000..90a6bd0
--- /dev/null
@@ -0,0 +1,251 @@
+/**************************************************************************
+
+Copyright 2004 Tungsten Graphics Inc., Cedar Park, Texas.
+
+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
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, 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 (including the next
+paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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 <keith@tungstengraphics.com>
+ */
+
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "vtxfmt.h"
+#include "dlist.h"
+#include "state.h"
+#include "light.h"
+#include "api_arrayelt.h"
+#include "api_noop.h"
+#include "t_vtx_api.h"
+#include "simple_list.h"
+
+
+#if defined(USE_X86_ASM) && !defined(HAVE_NONSTANDARD_GLAPIENTRY)
+
+#define EXTERN( FUNC )         \
+extern const char *FUNC;       \
+extern const char *FUNC##_end
+
+EXTERN( _x86_Attribute1fv );
+EXTERN( _x86_Attribute2fv );
+EXTERN( _x86_Attribute3fv );
+EXTERN( _x86_Attribute4fv );
+EXTERN( _x86_Vertex1fv );
+EXTERN( _x86_Vertex2fv );
+EXTERN( _x86_Vertex3fv );
+EXTERN( _x86_Vertex4fv );
+
+/* None of these used yet:
+ */
+EXTERN( _x86_dispatch_attrf );
+EXTERN( _x86_dispatch_attrfv );
+EXTERN( _x86_dispatch_multitexcoordf );
+EXTERN( _x86_dispatch_multitexcoordfv );
+EXTERN( _x86_dispatch_vertexattribf );
+EXTERN( _x86_dispatch_vertexattribfv );
+
+
+static void notify( void )
+{
+   GET_CURRENT_CONTEXT( ctx );
+   _tnl_wrap_filled_vertex( ctx );
+}
+
+#define DONT_KNOW_OFFSETS 1
+
+
+#define DFN( FUNC, CACHE, KEY )                                \
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );          \
+   char *start = (char *)&FUNC;                                \
+   char *end = (char *)&FUNC##_end;                    \
+   int offset = 0;                                     \
+   insert_at_head( &CACHE, dfn );                      \
+   dfn->key = KEY;                                     \
+   dfn->code = ALIGN_MALLOC( end - start, 16 );                \
+   memcpy (dfn->code, start, end - start)
+
+
+
+#define FIXUP( CODE, KNOWN_OFFSET, CHECKVAL, NEWVAL )  \
+do {                                                   \
+   GLuint subst = 0x10101010 + CHECKVAL;               \
+                                                       \
+   if (DONT_KNOW_OFFSETS) {                            \
+      while (*(int *)(CODE+offset) != subst) offset++; \
+      *(int *)(CODE+offset) = (int)(NEWVAL);           \
+      if (0) fprintf(stderr, "%s/%d: offset %d, new value: 0x%x\n", __FILE__, __LINE__, offset, (int)(NEWVAL)); \
+      offset += 4;                                     \
+   }                                                   \
+   else {                                              \
+      int *icode = (int *)(CODE+KNOWN_OFFSET);         \
+      assert (*icode == subst);                                \
+      *icode = (int)NEWVAL;                            \
+   }                                                   \
+} while (0)
+
+
+
+
+/* Build specialized versions of the immediate calls on the fly for
+ * the current state.  Generic x86 versions.
+ */
+
+static struct dynfn *makeX86Vertex1fv( GLcontext *ctx, int vertex_size )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Vertex1fv, tnl->vtx.cache.Vertex[1-1], vertex_size );
+
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 1, vertex_size - 1);
+   FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[1]);
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 4, (int)&notify);
+
+   return dfn;
+}
+
+static struct dynfn *makeX86Vertex2fv( GLcontext *ctx, int vertex_size )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Vertex2fv, tnl->vtx.cache.Vertex[2-1], vertex_size );
+
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 1, vertex_size - 2);
+   FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[2]);
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 4, (int)&notify);
+
+   return dfn;
+}
+
+static struct dynfn *makeX86Vertex3fv( GLcontext *ctx, int vertex_size )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Vertex3fv, tnl->vtx.cache.Vertex[3-1], vertex_size );
+
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 1, vertex_size - 3);
+   FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[3]);
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 4, (int)&notify);
+   return dfn;
+}
+
+static struct dynfn *makeX86Vertex4fv( GLcontext *ctx, int vertex_size )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Vertex4fv, tnl->vtx.cache.Vertex[4-1], vertex_size );
+
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 1, vertex_size - 4);
+   FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[4]);
+   FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
+   FIXUP(dfn->code, 0, 4, (int)&notify);
+
+   return dfn;
+}
+
+
+static struct dynfn *makeX86Attribute1fv( GLcontext *ctx, int dest )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Attribute1fv, tnl->vtx.cache.Attribute[1-1], dest );
+
+   FIXUP(dfn->code, 0, 0, dest); 
+
+   return dfn;
+}
+
+static struct dynfn *makeX86Attribute2fv( GLcontext *ctx, int dest )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Attribute2fv, tnl->vtx.cache.Attribute[2-1], dest );
+
+   FIXUP(dfn->code, 0, 0, dest); 
+   FIXUP(dfn->code, 0, 1, 4+dest); 
+
+   return dfn;
+}
+
+static struct dynfn *makeX86Attribute3fv( GLcontext *ctx, int dest )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Attribute3fv, tnl->vtx.cache.Attribute[3-1], dest );
+
+   FIXUP(dfn->code, 0, 0, dest); 
+   FIXUP(dfn->code, 0, 1, 4+dest); 
+   FIXUP(dfn->code, 0, 2, 8+dest);
+
+   return dfn;
+}
+
+static struct dynfn *makeX86Attribute4fv( GLcontext *ctx, int dest )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DFN ( _x86_Attribute4fv, tnl->vtx.cache.Attribute[4-1], dest );
+
+   FIXUP(dfn->code, 0, 0, dest); 
+   FIXUP(dfn->code, 0, 1, 4+dest); 
+   FIXUP(dfn->code, 0, 2, 8+dest);
+   FIXUP(dfn->code, 0, 3, 12+dest);
+
+   return dfn;
+}
+
+
+void _tnl_InitX86Codegen( struct dynfn_generators *gen )
+{
+   gen->Vertex[0] = makeX86Vertex1fv;
+   gen->Vertex[1] = makeX86Vertex2fv;
+   gen->Vertex[2] = makeX86Vertex3fv;
+   gen->Vertex[3] = makeX86Vertex4fv;
+   gen->Attribute[0] = makeX86Attribute1fv;
+   gen->Attribute[1] = makeX86Attribute2fv;
+   gen->Attribute[2] = makeX86Attribute3fv;
+   gen->Attribute[3] = makeX86Attribute4fv;
+}
+
+void _do_choose( void )
+{
+}
+
+#else 
+
+void _tnl_InitX86Codegen( struct dynfn_generators *gen )
+{
+   (void) gen;
+}
+
+#endif