Core of the future vertex engine. Isn't built yet, nor will be for a while...

Checkpoint commit.
This commit is contained in:
Keith Whitwell
2002-04-18 08:17:03 +00:00
parent ef65c60d88
commit 9ff3e9d992
5 changed files with 2365 additions and 0 deletions

675
src/mesa/tnl/t_vtx_api.c Normal file
View File

@@ -0,0 +1,675 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 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
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 "mtypes.h"
#include "colormac.h"
#include "simple_list.h"
#include "vtxfmt.h"
#include "tnl_vtx_api.h"
/* Fallback versions of all the entrypoints for situations where
* codegen isn't available. This is slowed significantly by all the
* gumph necessary to get to the tnl pointer.
*/
/* MultiTexcoord ends up with both of these branches, unfortunately
* (it may its own version of the macro after size-tracking is working).
*/
#define ATTRF( ATTR, N, A, B, C, D ) \
{ \
GET_CURRENT_CONTEXT( ctx ); \
TNLcontext *tnl = TNL_CONTEXT(ctx); \
\
if (((ATTR) & 0xf) == 0) { \
int i; \
\
if (N>0) tnl->dmaptr[0].f = A; \
if (N>1) tnl->dmaptr[1].f = B; \
if (N>2) tnl->dmaptr[2].f = C; \
if (N>3) tnl->dmaptr[3].f = D; \
\
for (i = N; i < tnl->vertex_size; i++) \
*tnl->dmaptr[i].i = tnl->vertex[i].i; \
\
tnl->dmaptr += tnl->vertex_size; \
\
if (--tnl->counter == 0) \
tnl->notify(); \
} \
else { \
GLfloat *dest = tnl->attrptr[(ATTR) & 0xf]; \
if (N>0) dest[0] = A; \
if (N>1) dest[1] = B; \
if (N>2) dest[2] = C; \
if (N>3) dest[3] = D; \
} \
}
#define ATTR4F( ATTR, A, B, C, D ) ATTRF( ATTR, 4, A, B, C, D )
#define ATTR3F( ATTR, A, B, C, D ) ATTRF( ATTR, 3, A, B, C, 1 )
#define ATTR2F( ATTR, A, B, C, D ) ATTRF( ATTR, 2, A, B, 0, 1 )
#define ATTR1F( ATTR, A, B, C, D ) ATTRF( ATTR, 1, A, 0, 0, 1 )
#define ATTR3UB( ATTR, A, B, C ) \
ATTR3F( ATTR, \
UBYTE_TO_FLOAT(A), \
UBYTE_TO_FLOAT(B), \
UBYTE_TO_FLOAT(C))
#define ATTR4UB( ATTR, A, B, C, D ) \
ATTR4F( ATTR, \
UBYTE_TO_FLOAT(A), \
UBYTE_TO_FLOAT(B), \
UBYTE_TO_FLOAT(C), \
UBYTE_TO_FLOAT(D))
/* Vertex
*/
static void tnl_Vertex2f( GLfloat x, GLfloat y )
{
ATTR2F( VERT_ATTRIB_POS, x, y );
}
static void tnl_Vertex2fv( const GLfloat *v )
{
ATTR2F( VERT_ATTRIB_POS, v[0], v[1] );
}
static void tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
{
ATTR3F( VERT_ATTRIB_POS, x, y, z );
}
static void tnl_Vertex3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_POS, v[0], v[1], v[2] );
}
static void tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
{
ATTR4F( VERT_ATTRIB_POS, x, y, z, w );
}
static void tnl_Vertex4fv( const GLfloat *v )
{
ATTR4F( VERT_ATTRIB_POS, v[0], v[1], v[2], v[3] );
}
/* Color
*/
static void tnl_Color3ub( GLubyte r, GLubyte g, GLubyte b )
{
ATTR3UB( VERT_ATTRIB_COLOR0, r, g, b );
}
static void tnl_Color3ubv( const GLubyte *v )
{
ATTR3UB( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] );
}
static void tnl_Color4ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
ATTR4UB( VERT_ATTRIB_COLOR0, r, g, b, a );
}
static void tnl_Color4ubv( const GLubyte *v )
{
ATTR4UB( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] );
}
static void tnl_Color3f( GLfloat r, GLfloat g, GLfloat b )
{
ATTR3F( VERT_ATTRIB_COLOR0, r, g, b );
}
static void tnl_Color3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] );
}
static void tnl_Color4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
ATTR4F( VERT_ATTRIB_COLOR0, r, g, b, a );
}
static void tnl_Color4fv( const GLfloat *v )
{
ATTR4F( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] );
}
/* Secondary Color
*/
static void tnl_SecondaryColor3ubEXT( GLubyte r, GLubyte g, GLubyte b )
{
ATTR3UB( VERT_ATTRIB_COLOR1, r, g, b );
}
static void tnl_SecondaryColor3ubvEXT( const GLubyte *v )
{
ATTR3UB( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] );
}
static void tnl_SecondaryColor3fEXT( GLfloat r, GLfloat g, GLfloat b )
{
ATTR3F( VERT_ATTRIB_COLOR1, r, g, b );
}
static void tnl_SecondaryColor3fvEXT( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] );
}
/* Fog Coord
*/
static void tnl_FogCoordfEXT( GLfloat f )
{
ATTR1F( VERT_ATTRIB_FOG, f );
}
static void tnl_FogCoordfvEXT( const GLfloat *v )
{
ATTR1F( VERT_ATTRIB_FOG, v[0] );
}
/* Normal
*/
static void tnl_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 )
{
ATTR3F( VERT_ATTRIB_NORMAL, n0, n1, n2 );
}
static void tnl_Normal3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] );
}
/* TexCoord
*/
static void tnl_TexCoord1f( GLfloat s )
{
ATTR1F( VERT_ATTRIB_TEX0, s );
}
static void tnl_TexCoord1fv( const GLfloat *v )
{
ATTR1F( VERT_ATTRIB_TEX0, v[0] );
}
static void tnl_TexCoord2f( GLfloat s, GLfloat t )
{
ATTR2F( VERT_ATTRIB_TEX0, s, t );
}
static void tnl_TexCoord2fv( const GLfloat *v )
{
ATTR2F( VERT_ATTRIB_TEX0, v[0], v[1] );
}
static void tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r )
{
ATTR3F( VERT_ATTRIB_TEX0, s, t, r );
}
static void tnl_TexCoord3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_TEX0, v[0], v[1], v[2] );
}
static void tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
{
ATTR4F( VERT_ATTRIB_TEX0, s, t, r, q );
}
static void tnl_TexCoord4fv( const GLfloat *v )
{
ATTR4F( VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3] );
}
/* MultiTexcoord
*/
static void tnl_MultiTexCoord1fARB( GLenum target, GLfloat s )
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR1F( attr, s );
}
static void tnl_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR1F( attr, v[0] );
}
static void tnl_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR2F( attr, s, t );
}
static void tnl_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR2F( attr, v[0], v[1] );
}
static void tnl_MultiTexCoord3fARB( GLenum target, GLfloat s, GLfloat t,
GLfloat r)
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR3F( attr, s, t, r );
}
static void tnl_MultiTexCoord3fvARB( GLenum target, const GLfloat *v )
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR3F( attr, v[0], v[1], v[2] );
}
static void tnl_MultiTexCoord4fARB( GLenum target, GLfloat s, GLfloat t,
GLfloat r, GLfloat q )
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR4F( attr, s, t, r, q );
}
static void tnl_MultiTexCoord4fvARB( GLenum target, const GLfloat *v )
{
GLint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
ATTR4F( attr, v[0], v[1], v[2], v[3] );
}
/* NV_vertex_program:
*
* *** Need second dispatch layer above this for size tracking. One
* *** dispatch layer handles both VertexAttribute and MultiTexCoord
*/
static void tnl_VertexAttrib1fNV( GLuint index, GLfloat s )
{
ATTR1F( index, s );
}
static void tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
{
ATTR1F( index, v[0] );
}
static void tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t )
{
ATTR2F( index, s, t );
}
static void tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
{
ATTR2F( index, v[0], v[1] );
}
static void tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t,
GLfloat r )
{
ATTR3F( index, s, t, r );
}
static void tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
{
ATTR3F( index, v[0], v[1], v[2] );
}
static void tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t,
GLfloat r, GLfloat q )
{
ATTR4F( index, s, t, r, q );
}
static void tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
{
ATTR4F( index, v[0], v[1], v[2], v[3] );
}
/* Miscellaneous: (These don't alias NV attributes, right?)
*/
static void tnl_EdgeFlag( GLboolean flag )
{
GET_TNL;
tnl->edgeflagptr[0] = flag;
}
static void tnl_EdgeFlagv( const GLboolean *flag )
{
GET_TNL;
tnl->edgeflagptr[0] = *flag;
}
static void tnl_Indexi( GLint idx )
{
GET_TNL;
tnl->indexptr[0] = idx;
}
static void tnl_Indexiv( const GLint *idx )
{
GET_TNL;
tnl->indexptr[0] = *idx;
}
/* Could use dispatch switching to build 'ranges' of eval vertices for
* each type, avoiding need for flags. (Make
* evalcoords/evalpoints/vertices/attr0 mutually exclusive)
* --> In which case, may as well use Vertex{12}f{v} here.
*/
static void _tnl_EvalCoord1f( GLfloat u )
{
ATTR1F( VERT_ATTRIB_POS, u );
}
static void _tnl_EvalCoord1fv( const GLfloat *v )
{
ATTR1F( VERT_ATTRIB_POS, v[0] );
}
static void _tnl_EvalCoord2f( GLfloat u, GLfloat v )
{
ATTR2F( VERT_ATTRIB_POS, u, v );
}
static void _tnl_EvalCoord2fv( const GLfloat *v )
{
ATTR2F( VERT_ATTRIB_POS, v[0], v[1] );
}
/* Materials:
* *** Treat as more vertex attributes
*/
static void _tnl_Materialfv( GLenum face, GLenum pname,
const GLfloat *params )
{
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
if (tnl->prim[0] != GL_POLYGON+1) {
VFMT_FALLBACK( __FUNCTION__ );
glMaterialfv( face, pname, params );
return;
}
_mesa_noop_Materialfv( face, pname, params );
}
/* Codegen support
*/
static struct dynfn *lookup( struct dynfn *l, int key )
{
struct dynfn *f;
foreach( f, l ) {
if (f->key == key)
return f;
}
return 0;
}
/* Can't use the loopback template for this:
*/
#define CHOOSE(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \
static void choose_##FN ARGS1 \
{ \
int key = tnl->vertex_format & (MASK|ACTIVE); \
struct dynfn *dfn = lookup( &tnl->dfn_cache.FN, key ); \
\
if (dfn == 0) \
dfn = tnl->codegen.FN( &vb, key ); \
else if (MESA_VERBOSE & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- cached codegen\n", __FUNCTION__ ); \
\
if (dfn) \
tnl->context->Exec->FN = (FNTYPE)(dfn->code); \
else { \
if (MESA_VERBOSE & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \
tnl->context->Exec->FN = tnl_##FN; \
} \
\
tnl->context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
tnl->context->Exec->FN ARGS2; \
}
CHOOSE(Normal3f, p3f, 3, VERT_ATTRIB_NORMAL,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Normal3fv, pfv, 3, VERT_ATTRIB_NORMAL,
(const GLfloat *v), (v))
CHOOSE(Color4ub, p4ub, 4, VERT_ATTRIB_COLOR0,
(GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d))
CHOOSE(Color4ubv, pubv, 4, VERT_ATTRIB_COLOR0,
(const GLubyte *v), (v))
CHOOSE(Color3ub, p3ub, 3, VERT_ATTRIB_COLOR0,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE(Color3ubv, pubv, 3, VERT_ATTRIB_COLOR0,
(const GLubyte *v), (v))
CHOOSE(Color4f, p4f, 4, VERT_ATTRIB_COLOR0,
(GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d))
CHOOSE(Color4fv, pfv, 4, VERT_ATTRIB_COLOR0,
(const GLfloat *v), (v))
CHOOSE(Color3f, p3f, 3, VERT_ATTRIB_COLOR0,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE(Color3fv, pfv, 3, VERT_ATTRIB_COLOR0,
(const GLfloat *v), (v))
CHOOSE(SecondaryColor3ubEXT, p3ub, VERT_ATTRIB_COLOR1,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE(SecondaryColor3ubvEXT, pubv, VERT_ATTRIB_COLOR1,
(const GLubyte *v), (v))
CHOOSE(SecondaryColor3fEXT, p3f, VERT_ATTRIB_COLOR1,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE(SecondaryColor3fvEXT, pfv, VERT_ATTRIB_COLOR1,
(const GLfloat *v), (v))
CHOOSE(TexCoord2f, p2f, VERT_ATTRIB_TEX0,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(TexCoord2fv, pfv, VERT_ATTRIB_TEX0,
(const GLfloat *v), (v))
CHOOSE(TexCoord1f, p1f, VERT_ATTRIB_TEX0,
(GLfloat a), (a))
CHOOSE(TexCoord1fv, pfv, VERT_ATTRIB_TEX0,
(const GLfloat *v), (v))
CHOOSE(MultiTexCoord2fARB, pe2f, VERT_ATTRIB_TEX0,
(GLenum u,GLfloat a,GLfloat b), (u,a,b))
CHOOSE(MultiTexCoord2fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,const GLfloat *v), (u,v))
CHOOSE(MultiTexCoord1fARB, pe1f, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,GLfloat a), (u,a))
CHOOSE(MultiTexCoord1fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,const GLfloat *v), (u,v))
CHOOSE(Vertex3f, p3f, VERT_ATTRIB_POS,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Vertex3fv, pfv, VERT_ATTRIB_POS,
(const GLfloat *v), (v))
CHOOSE(Vertex2f, p2f, VERT_ATTRIB_POS,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(Vertex2fv, pfv, VERT_ATTRIB_POS,
(const GLfloat *v), (v))
void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt )
{
vfmt->Color3f = choose_Color3f;
vfmt->Color3fv = choose_Color3fv;
vfmt->Color3ub = choose_Color3ub;
vfmt->Color3ubv = choose_Color3ubv;
vfmt->Color4f = choose_Color4f;
vfmt->Color4fv = choose_Color4fv;
vfmt->Color4ub = choose_Color4ub;
vfmt->Color4ubv = choose_Color4ubv;
vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT;
vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT;
vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT;
vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT;
vfmt->MultiTexCoord1fARB = choose_MultiTexCoord1fARB;
vfmt->MultiTexCoord1fvARB = choose_MultiTexCoord1fvARB;
vfmt->MultiTexCoord2fARB = choose_MultiTexCoord2fARB;
vfmt->MultiTexCoord2fvARB = choose_MultiTexCoord2fvARB;
vfmt->Normal3f = choose_Normal3f;
vfmt->Normal3fv = choose_Normal3fv;
vfmt->TexCoord1f = choose_TexCoord1f;
vfmt->TexCoord1fv = choose_TexCoord1fv;
vfmt->TexCoord2f = choose_TexCoord2f;
vfmt->TexCoord2fv = choose_TexCoord2fv;
vfmt->Vertex2f = choose_Vertex2f;
vfmt->Vertex2fv = choose_Vertex2fv;
vfmt->Vertex3f = choose_Vertex3f;
vfmt->Vertex3fv = choose_Vertex3fv;
vfmt->TexCoord3f = choose_TexCoord3f;
vfmt->TexCoord3fv = choose_TexCoord3fv;
vfmt->TexCoord4f = choose_TexCoord4f;
vfmt->TexCoord4fv = choose_TexCoord4fv;
vfmt->MultiTexCoord3fARB = choose_MultiTexCoord3fARB;
vfmt->MultiTexCoord3fvARB = choose_MultiTexCoord3fvARB;
vfmt->MultiTexCoord4fARB = choose_MultiTexCoord4fARB;
vfmt->MultiTexCoord4fvARB = choose_MultiTexCoord4fvARB;
vfmt->Vertex4f = choose_Vertex4f;
vfmt->Vertex4fv = choose_Vertex4fv;
vfmt->FogCoordfvEXT = choose_FogCoordfvEXT;
vfmt->FogCoordfEXT = choose_FogCoordfEXT;
vfmt->EdgeFlag = choose_EdgeFlag;
vfmt->EdgeFlagv = choose_EdgeFlagv;
vfmt->Indexi = choose_Indexi;
vfmt->Indexiv = choose_Indexiv;
vfmt->EvalCoord1f = choose_EvalCoord1f;
vfmt->EvalCoord1fv = choose_EvalCoord1fv;
vfmt->EvalCoord2f = choose_EvalCoord2f;
vfmt->EvalCoord2fv = choose_EvalCoord2fv;
vfmt->EvalMesh1 = choose_EvalMesh1;
vfmt->EvalMesh2 = choose_EvalMesh2;
vfmt->EvalPoint1 = choose_EvalPoint1;
vfmt->EvalPoint2 = choose_EvalPoint2;
vfmt->Materialfv = _tnl_Materialfv;
}
static struct dynfn *codegen_noop( struct _vb *vb, int key )
{
(void) vb; (void) key;
return 0;
}
void _tnl_InitCodegen( struct dfn_generators *gen )
{
gen->Vertex2f = codegen_noop;
gen->Vertex2fv = codegen_noop;
gen->Vertex3f = codegen_noop;
gen->Vertex3fv = codegen_noop;
gen->Vertex4f = codegen_noop;
gen->Vertex4fv = codegen_noop;
gen->Attr1f = codegen_noop;
gen->Attr1fv = codegen_noop;
gen->Attr2f = codegen_noop;
gen->Attr2fv = codegen_noop;
gen->Attr3f = codegen_noop;
gen->Attr3fv = codegen_noop;
gen->Attr4f = codegen_noop;
gen->Attr4fv = codegen_noop;
gen->Attr3ub = codegen_noop;
gen->Attr3ubv = codegen_noop;
gen->Attr4ub = codegen_noop;
gen->Attr4ubv = codegen_noop;
/* Probably need two versions of this, one for the front end
* (double dispatch), one for the back end (do the work) -- but
* will also need a second level of CHOOSE functions?
* -- Generate the dispatch layer using the existing templates somehow.
* -- Generate the backend and 2nd level choosers here.
* -- No need for a chooser on the top level.
* -- Can aliasing help -- ie can NVAttr1f == Attr1f/Vertex2f at this level (index is known)
*/
gen->NVAttr1f = codegen_noop;
gen->NVAttr1fv = codegen_noop;
gen->NVAttr2f = codegen_noop;
gen->NVAttr2fv = codegen_noop;
gen->NVAttr3f = codegen_noop;
gen->NVAttr3fv = codegen_noop;
gen->NVAttr4f = codegen_noop;
gen->NVAttr4fv = codegen_noop;
gen->MTAttr1f = codegen_noop;
gen->MTAttr1fv = codegen_noop;
gen->MTAttr2f = codegen_noop;
gen->MTAttr2fv = codegen_noop;
gen->MTAttr3f = codegen_noop;
gen->MTAttr3fv = codegen_noop;
gen->MTAttr4f = codegen_noop;
gen->MTAttr4fv = codegen_noop;
if (!getenv("MESA_NO_CODEGEN")) {
#if defined(USE_X86_ASM)
_tnl_InitX86Codegen( gen );
#endif
#if defined(USE_SSE_ASM)
_tnl_InitSSECodegen( gen );
#endif
#if defined(USE_3DNOW_ASM)
#endif
#if defined(USE_SPARC_ASM)
#endif
}
}

234
src/mesa/tnl/t_vtx_api.h Normal file
View File

@@ -0,0 +1,234 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 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
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>
*
*/
#ifndef __RADEON_VTXFMT_H__
#define __RADEON_VTXFMT_H__
#ifdef GLX_DIRECT_RENDERING
#include "_tnl__context.h"
extern void _tnl_UpdateVtxfmt( GLcontext *ctx );
extern void _tnl_InitVtxfmt( GLcontext *ctx );
extern void _tnl_InvalidateVtxfmt( GLcontext *ctx );
extern void _tnl_DestroyVtxfmt( GLcontext *ctx );
typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat );
typedef void (*p3f)( GLfloat, GLfloat, GLfloat );
typedef void (*p2f)( GLfloat, GLfloat );
typedef void (*p1f)( GLfloat );
typedef void (*pe2f)( GLenum, GLfloat, GLfloat );
typedef void (*pe1f)( GLenum, GLfloat );
typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
typedef void (*p3ub)( GLubyte, GLubyte, GLubyte );
typedef void (*pfv)( const GLfloat * );
typedef void (*pefv)( GLenum, const GLfloat * );
typedef void (*pubv)( const GLubyte * );
/* Want to keep a cache of these around. Each is parameterized by
* only a single value which has only a small range. Only expect a
* few, so just rescan the list each time?
*/
struct dynfn {
struct dynfn *next, *prev;
int key;
char *code;
};
struct dfn_lists {
struct dynfn Vertex2f;
struct dynfn Vertex2fv;
struct dynfn Vertex3f;
struct dynfn Vertex3fv;
struct dynfn Color4ub;
struct dynfn Color4ubv;
struct dynfn Color3ub;
struct dynfn Color3ubv;
struct dynfn Color4f;
struct dynfn Color4fv;
struct dynfn Color3f;
struct dynfn Color3fv;
struct dynfn SecondaryColor3ubEXT;
struct dynfn SecondaryColor3ubvEXT;
struct dynfn SecondaryColor3fEXT;
struct dynfn SecondaryColor3fvEXT;
struct dynfn Normal3f;
struct dynfn Normal3fv;
struct dynfn TexCoord2f;
struct dynfn TexCoord2fv;
struct dynfn TexCoord1f;
struct dynfn TexCoord1fv;
struct dynfn MultiTexCoord2fARB;
struct dynfn MultiTexCoord2fvARB;
struct dynfn MultiTexCoord1fARB;
struct dynfn MultiTexCoord1fvARB;
};
struct _vb;
struct dfn_generators {
struct dynfn *(*Vertex2f)( struct _vb *, int );
struct dynfn *(*Vertex2fv)( struct _vb *, int );
struct dynfn *(*Vertex3f)( struct _vb *, int );
struct dynfn *(*Vertex3fv)( struct _vb *, int );
struct dynfn *(*Color4ub)( struct _vb *, int );
struct dynfn *(*Color4ubv)( struct _vb *, int );
struct dynfn *(*Color3ub)( struct _vb *, int );
struct dynfn *(*Color3ubv)( struct _vb *, int );
struct dynfn *(*Color4f)( struct _vb *, int );
struct dynfn *(*Color4fv)( struct _vb *, int );
struct dynfn *(*Color3f)( struct _vb *, int );
struct dynfn *(*Color3fv)( struct _vb *, int );
struct dynfn *(*SecondaryColor3ubEXT)( struct _vb *, int );
struct dynfn *(*SecondaryColor3ubvEXT)( struct _vb *, int );
struct dynfn *(*SecondaryColor3fEXT)( struct _vb *, int );
struct dynfn *(*SecondaryColor3fvEXT)( struct _vb *, int );
struct dynfn *(*Normal3f)( struct _vb *, int );
struct dynfn *(*Normal3fv)( struct _vb *, int );
struct dynfn *(*TexCoord2f)( struct _vb *, int );
struct dynfn *(*TexCoord2fv)( struct _vb *, int );
struct dynfn *(*TexCoord1f)( struct _vb *, int );
struct dynfn *(*TexCoord1fv)( struct _vb *, int );
struct dynfn *(*MultiTexCoord2fARB)( struct _vb *, int );
struct dynfn *(*MultiTexCoord2fvARB)( struct _vb *, int );
struct dynfn *(*MultiTexCoord1fARB)( struct _vb *, int );
struct dynfn *(*MultiTexCoord1fvARB)( struct _vb *, int );
};
struct prim {
GLuint start;
GLuint end;
GLuint prim;
};
#define _TNL__MAX_PRIMS 64
struct tnl_vbinfo {
/* Keep these first: referenced from codegen templates:
*/
GLint counter;
GLint *dmaptr;
void (*notify)( void );
union { float f; int i; GLubyte ub4[4]; } vertex[16*4];
GLfloat *attrptr[16];
GLuint size[16];
GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */
GLuint primflags;
GLboolean installed;
GLboolean recheck;
GLint vertex_size;
GLint initial_counter;
GLint nrverts;
GLuint vertex_format;
GLuint installed_vertex_format;
struct prim primlist[RADEON_MAX_PRIMS];
int nrprims;
struct dfn_lists dfn_cache;
struct dfn_generators codegen;
GLvertexformat vtxfmt;
};
extern void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt );
#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
int *icode = (int *)(CODE+OFFSET); \
assert (*icode == CHECKVAL); \
*icode = (int)NEWVAL; \
} while (0)
/* Useful for figuring out the offsets:
*/
#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \
fprintf(stderr, "%s/%d CVAL %x OFFSET %d\n", __FUNCTION__, \
__LINE__, CHECKVAL, OFFSET); \
*(int *)(CODE+OFFSET) = (int)NEWVAL; \
OFFSET += 4; \
} while (0)
/*
*/
void _tnl_InitCodegen( struct dfn_generators *gen );
void _tnl_InitX86Codegen( struct dfn_generators *gen );
void _tnl_InitSSECodegen( struct dfn_generators *gen );
void _tnl_copy_to_current( GLcontext *ctx );
/* Defined in tnl_vtxfmt_c.c.
*/
struct dynfn *tnl_makeX86Vertex2f( TNLcontext *, int );
struct dynfn *tnl_makeX86Vertex2fv( TNLcontext *, int );
struct dynfn *tnl_makeX86Vertex3f( TNLcontext *, int );
struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4ub( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4ubv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3ub( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3ubv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4f( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4fv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3f( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3fv( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3ubEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3ubvEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3fEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3fvEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86Normal3f( TNLcontext *, int );
struct dynfn *tnl_makeX86Normal3fv( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord2f( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord2fv( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord1f( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord1fv( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord2fARB( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord2fvARB( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord1fARB( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord1fvARB( TNLcontext *, int );
#endif
#endif

636
src/mesa/tnl/t_vtx_exec.c Normal file
View File

@@ -0,0 +1,636 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 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
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 "api_noop.h"
#include "api_arrayelt.h"
#include "context.h"
#include "mem.h"
#include "mmath.h"
#include "mtypes.h"
#include "enums.h"
#include "glapi.h"
#include "colormac.h"
#include "light.h"
#include "state.h"
#include "vtxfmt.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_array_api.h"
static void _tnl_FlushVertices( GLcontext *, GLuint );
void tnl_copy_to_current( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint flag = tnl->vertex_format;
GLint i;
assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT);
for (i = 0 ; i < 16 ; i++)
if (flag & (1<<i))
COPY_4FV( ctx->Current.Attrib[i], tnl->attribptr[i] );
if (flag & VERT_BIT_INDEX)
ctx->Current.Index = tnl->indexptr[0];
if (flag & VERT_BIT_EDGEFLAG)
ctx->Current.EdgeFlag = tnl->edgeflagptr[0];
if (flag & VERT_BIT_MATERIAL) {
_mesa_update_material( ctx,
IM->Material[IM->LastMaterial],
IM->MaterialOrMask );
tnl->Driver.NotifyMaterialChange( ctx );
}
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
}
static GLboolean discreet_gl_prim[GL_POLYGON+1] = {
1, /* 0 points */
1, /* 1 lines */
0, /* 2 line_strip */
0, /* 3 line_loop */
1, /* 4 tris */
0, /* 5 tri_fan */
0, /* 6 tri_strip */
1, /* 7 quads */
0, /* 8 quadstrip */
0, /* 9 poly */
};
/* Optimize the primitive list: ONLY FOR EXECUTE ATM
*/
static void optimize_prims( TNLcontext *tnl )
{
int i, j;
if (tnl->nrprims <= 1)
return;
for (j = 0, i = 1 ; i < tnl->nrprims; i++) {
int pj = tnl->primlist[j].prim & 0xf;
int pi = tnl->primlist[i].prim & 0xf;
if (pj == pi && discreet_gl_prim[pj] &&
tnl->primlist[i].start == tnl->primlist[j].end) {
tnl->primlist[j].end = tnl->primlist[i].end;
}
else {
j++;
if (j != i) tnl->primlist[j] = tnl->primlist[i];
}
}
tnl->nrprims = j+1;
}
/* Bind vertex buffer pointers, run pipeline:
*/
static void flush_prims( TNLcontext *tnl )
{
int i,j;
tnl->dma.current.ptr = tnl->dma.current.start +=
(tnl->initial_counter - tnl->counter) * tnl->vertex_size * 4;
tnl->tcl.vertex_format = tnl->vertex_format;
tnl->tcl.aos_components[0] = &tmp;
tnl->tcl.nr_aos_components = 1;
tnl->dma.flush = 0;
tnl->Driver.RunPipeline( ... );
tnl->nrprims = 0;
}
static void start_prim( TNLcontext *tnl, GLuint mode )
{
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s %d\n", __FUNCTION__,
tnl->initial_counter - tnl->counter);
tnl->primlist[tnl->nrprims].start = tnl->initial_counter - tnl->counter;
tnl->primlist[tnl->nrprims].prim = mode;
}
static void note_last_prim( TNLcontext *tnl, GLuint flags )
{
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s %d\n", __FUNCTION__,
tnl->initial_counter - tnl->counter);
if (tnl->prim[0] != GL_POLYGON+1) {
tnl->primlist[tnl->nrprims].prim |= flags;
tnl->primlist[tnl->nrprims].end = tnl->initial_counter - tnl->counter;
if (++tnl->nrprims == TNL_MAX_PRIMS)
flush_prims( tnl );
}
}
static void copy_vertex( TNLcontext *tnl, GLuint n, GLfloat *dst )
{
GLuint i;
GLfloat *src = (GLfloat *)(tnl->dma.current.address +
tnl->dma.current.ptr +
(tnl->primlist[tnl->nrprims].start + n) *
tnl->vertex_size * 4);
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "copy_vertex %d\n",
tnl->primlist[tnl->nrprims].start + n);
for (i = 0 ; i < tnl->vertex_size; i++) {
dst[i] = src[i];
}
}
/* NOTE: This actually reads the copied vertices back from uncached
* memory. Could also use the counter/notify mechanism to populate
* tmp on the fly as vertices are generated.
*/
static GLuint copy_wrapped_verts( TNLcontext *tnl, GLfloat (*tmp)[15] )
{
GLuint ovf, i;
GLuint nr = (tnl->initial_counter - tnl->counter) - tnl->primlist[tnl->nrprims].start;
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s %d verts\n", __FUNCTION__, nr);
switch( tnl->prim[0] )
{
case GL_POINTS:
return 0;
case GL_LINES:
ovf = nr&1;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_TRIANGLES:
ovf = nr%3;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_QUADS:
ovf = nr&3;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_LINE_STRIP:
if (nr == 0)
return 0;
copy_vertex( tnl, nr-1, tmp[0] );
return 1;
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
if (nr == 0)
return 0;
else if (nr == 1) {
copy_vertex( tnl, 0, tmp[0] );
return 1;
} else {
copy_vertex( tnl, 0, tmp[0] );
copy_vertex( tnl, nr-1, tmp[1] );
return 2;
}
case GL_TRIANGLE_STRIP:
ovf = MIN2( nr-1, 2 );
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_QUAD_STRIP:
ovf = MIN2( nr-1, 2 );
if (nr > 2) ovf += nr&1;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
default:
assert(0);
return 0;
}
}
/* Extend for vertex-format changes on wrap:
*/
static void wrap_buffer( void )
{
TNLcontext *tnl = tnl->tnl;
GLfloat tmp[3][15];
GLuint i, nrverts;
if (MESA_VERBOSE & (DEBUG_VFMT|DEBUG_PRIMS))
fprintf(stderr, "%s %d\n", __FUNCTION__,
tnl->initial_counter - tnl->counter);
/* Don't deal with parity. *** WONT WORK FOR COMPILE
*/
if ((((tnl->initial_counter - tnl->counter) -
tnl->primlist[tnl->nrprims].start) & 1)) {
tnl->counter++;
tnl->initial_counter++;
return;
}
/* Copy vertices out of dma:
*/
nrverts = copy_dma_verts( tnl, tmp );
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%d vertices to copy\n", nrverts);
/* Finish the prim at this point:
*/
note_last_prim( tnl, 0 );
flush_prims( tnl );
/* Reset counter, dmaptr
*/
tnl->dmaptr = (int *)(tnl->dma.current.ptr + tnl->dma.current.address);
tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) /
(tnl->vertex_size * 4);
tnl->counter--;
tnl->initial_counter = tnl->counter;
tnl->notify = wrap_buffer;
tnl->dma.flush = flush_prims;
start_prim( tnl, tnl->prim[0] );
/* Reemit saved vertices
* *** POSSIBLY IN NEW FORMAT
* --> Can't always extend at end of vertex?
*/
for (i = 0 ; i < nrverts; i++) {
if (MESA_VERBOSE & DEBUG_VERTS) {
int j;
fprintf(stderr, "re-emit vertex %d to %p\n", i, tnl->dmaptr);
if (MESA_VERBOSE & DEBUG_VERBOSE)
for (j = 0 ; j < tnl->vertex_size; j++)
fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
}
memcpy( tnl->dmaptr, tmp[i], tnl->vertex_size * 4 );
tnl->dmaptr += tnl->vertex_size;
tnl->counter--;
}
}
/* Always follow data, don't try to predict what's necessary.
*/
static GLboolean check_vtx_fmt( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
TNL_NEWPRIM(tnl);
tnl->vertex_format = VERT_BIT_POS;
tnl->prim = &ctx->Driver.CurrentExecPrimitive;
/* Currently allow the full 4 components per attrib. Can use the
* mechanism from radeon driver color handling to reduce this (and
* also to store ubyte colors where these are incoming). This
* won't work for compile mode.
*
* Only adding components when they are first received eliminates
* the need for displaylist fixup, as there are no 'empty' slots
* at the start of buffers.
*/
for (i = 0 ; i < 16 ; i++) {
if (ind & (1<<i)) {
tnl->attribptr[i] = &tnl->vertex[tnl->vertex_size].f;
tnl->vertex_size += 4;
tnl->attribptr[i][0] = ctx->Current.Attrib[i][0];
tnl->attribptr[i][1] = ctx->Current.Attrib[i][1];
tnl->attribptr[i][2] = ctx->Current.Attrib[i][2];
tnl->attribptr[i][3] = ctx->Current.Attrib[i][3];
}
else
tnl->attribptr[i] = ctx->Current.Attrib[i];
}
/* Edgeflag, Index:
*/
for (i = 16 ; i < 18 ; i++)
;
/* Materials:
*/
for (i = 18 ; i < 28 ; i++)
;
/* Eval:
*/
for (i = 28 ; i < 29 ; i++)
;
if (tnl->installed_vertex_format != tnl->vertex_format) {
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "reinstall on vertex_format change\n");
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
tnl->installed_vertex_format = tnl->vertex_format;
}
return GL_TRUE;
}
void _tnl_InvalidateVtxfmt( GLcontext *ctx )
{
tnl->recheck = GL_TRUE;
tnl->fell_back = GL_FALSE;
}
static void _tnl_ValidateVtxfmt( GLcontext *ctx )
{
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
if (ctx->Driver.NeedFlush)
ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
tnl->recheck = GL_FALSE;
if (check_vtx_fmt( ctx )) {
if (!tnl->installed) {
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "reinstall (new install)\n");
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
ctx->Driver.FlushVertices = _tnl_FlushVertices;
tnl->installed = GL_TRUE;
}
else
fprintf(stderr, "%s: already installed", __FUNCTION__);
}
else {
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s: failed\n", __FUNCTION__);
if (tnl->installed) {
if (tnl->tnl->dma.flush)
tnl->tnl->dma.flush( tnl->tnl );
_tnl_wakeup_exec( ctx );
tnl->installed = GL_FALSE;
}
}
}
/* Begin/End
*/
static void _tnl_Begin( GLenum mode )
{
GLcontext *ctx = tnl->context;
TNLcontext *tnl = tnl->tnl;
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
return;
}
if (tnl->prim[0] != GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
return;
}
if (ctx->NewState)
_mesa_update_state( ctx );
if (tnl->recheck)
_tnl_ValidateVtxfmt( ctx );
if (tnl->dma.flush && tnl->counter < 12) {
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__);
flush_prims( tnl );
}
if (!tnl->dma.flush) {
if (tnl->dma.current.ptr + 12*tnl->vertex_size*4 >
tnl->dma.current.end) {
TNL_NEWPRIM( tnl );
_tnl_RefillCurrentDmaRegion( tnl );
}
tnl->dmaptr = (int *)(tnl->dma.current.address + tnl->dma.current.ptr);
tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) /
(tnl->vertex_size * 4);
tnl->counter--;
tnl->initial_counter = tnl->counter;
tnl->notify = wrap_buffer;
tnl->dma.flush = flush_prims;
tnl->context->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
}
tnl->prim[0] = mode;
start_prim( tnl, mode | PRIM_BEGIN );
}
static void _tnl_End( void )
{
TNLcontext *tnl = tnl->tnl;
GLcontext *ctx = tnl->context;
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
if (tnl->prim[0] == GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
return;
}
note_last_prim( tnl, PRIM_END );
tnl->prim[0] = GL_POLYGON+1;
}
static void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
{
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(tnl->installed);
if (flags & FLUSH_UPDATE_CURRENT) {
_tnl_copy_to_current( ctx );
if (MESA_VERBOSE & DEBUG_VFMT)
fprintf(stderr, "reinstall on update_current\n");
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
}
if (flags & FLUSH_STORED_VERTICES) {
TNLcontext *tnl = TNL_CONTEXT( ctx );
assert (tnl->dma.flush == 0 ||
tnl->dma.flush == flush_prims);
if (tnl->dma.flush == flush_prims)
flush_prims( TNL_CONTEXT( ctx ) );
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
}
}
/* At this point, don't expect very many versions of each function to
* be generated, so not concerned about freeing them?
*/
static void _tnl_InitVtxfmt( GLcontext *ctx )
{
GLvertexformat *vfmt = &(tnl->vtxfmt);
MEMSET( vfmt, 0, sizeof(GLvertexformat) );
/* Hook in chooser functions for codegen, etc:
*/
_tnl_InitVtxfmtChoosers( vfmt );
/* Handled fully in supported states, but no codegen:
*/
vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
vfmt->Begin = _tnl_Begin;
vfmt->End = _tnl_End;
tnl->context = ctx;
tnl->tnl = TNL_CONTEXT(ctx);
tnl->prim = &ctx->Driver.CurrentExecPrimitive;
tnl->primflags = 0;
make_empty_list( &tnl->dfn_cache.Vertex2f );
make_empty_list( &tnl->dfn_cache.Vertex2fv );
make_empty_list( &tnl->dfn_cache.Vertex3f );
make_empty_list( &tnl->dfn_cache.Vertex3fv );
make_empty_list( &tnl->dfn_cache.Color4ub );
make_empty_list( &tnl->dfn_cache.Color4ubv );
make_empty_list( &tnl->dfn_cache.Color3ub );
make_empty_list( &tnl->dfn_cache.Color3ubv );
make_empty_list( &tnl->dfn_cache.Color4f );
make_empty_list( &tnl->dfn_cache.Color4fv );
make_empty_list( &tnl->dfn_cache.Color3f );
make_empty_list( &tnl->dfn_cache.Color3fv );
make_empty_list( &tnl->dfn_cache.SecondaryColor3fEXT );
make_empty_list( &tnl->dfn_cache.SecondaryColor3fvEXT );
make_empty_list( &tnl->dfn_cache.SecondaryColor3ubEXT );
make_empty_list( &tnl->dfn_cache.SecondaryColor3ubvEXT );
make_empty_list( &tnl->dfn_cache.Normal3f );
make_empty_list( &tnl->dfn_cache.Normal3fv );
make_empty_list( &tnl->dfn_cache.TexCoord2f );
make_empty_list( &tnl->dfn_cache.TexCoord2fv );
make_empty_list( &tnl->dfn_cache.TexCoord1f );
make_empty_list( &tnl->dfn_cache.TexCoord1fv );
make_empty_list( &tnl->dfn_cache.MultiTexCoord2fARB );
make_empty_list( &tnl->dfn_cache.MultiTexCoord2fvARB );
make_empty_list( &tnl->dfn_cache.MultiTexCoord1fARB );
make_empty_list( &tnl->dfn_cache.MultiTexCoord1fvARB );
_tnl_InitCodegen( &tnl->codegen );
}
static void free_funcs( struct dynfn *l )
{
struct dynfn *f, *tmp;
foreach_s (f, tmp, l) {
remove_from_list( f );
ALIGN_FREE( f->code );
FREE( f );
}
}
static void _tnl_DestroyVtxfmt( GLcontext *ctx )
{
count_funcs();
free_funcs( &tnl->dfn_cache.Vertex2f );
free_funcs( &tnl->dfn_cache.Vertex2fv );
free_funcs( &tnl->dfn_cache.Vertex3f );
free_funcs( &tnl->dfn_cache.Vertex3fv );
free_funcs( &tnl->dfn_cache.Color4ub );
free_funcs( &tnl->dfn_cache.Color4ubv );
free_funcs( &tnl->dfn_cache.Color3ub );
free_funcs( &tnl->dfn_cache.Color3ubv );
free_funcs( &tnl->dfn_cache.Color4f );
free_funcs( &tnl->dfn_cache.Color4fv );
free_funcs( &tnl->dfn_cache.Color3f );
free_funcs( &tnl->dfn_cache.Color3fv );
free_funcs( &tnl->dfn_cache.SecondaryColor3ubEXT );
free_funcs( &tnl->dfn_cache.SecondaryColor3ubvEXT );
free_funcs( &tnl->dfn_cache.SecondaryColor3fEXT );
free_funcs( &tnl->dfn_cache.SecondaryColor3fvEXT );
free_funcs( &tnl->dfn_cache.Normal3f );
free_funcs( &tnl->dfn_cache.Normal3fv );
free_funcs( &tnl->dfn_cache.TexCoord2f );
free_funcs( &tnl->dfn_cache.TexCoord2fv );
free_funcs( &tnl->dfn_cache.TexCoord1f );
free_funcs( &tnl->dfn_cache.TexCoord1fv );
free_funcs( &tnl->dfn_cache.MultiTexCoord2fARB );
free_funcs( &tnl->dfn_cache.MultiTexCoord2fvARB );
free_funcs( &tnl->dfn_cache.MultiTexCoord1fARB );
free_funcs( &tnl->dfn_cache.MultiTexCoord1fvARB );
}

93
src/mesa/tnl/t_vtx_sse.c Normal file
View File

@@ -0,0 +1,93 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 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
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 <stdio.h>
#include <assert.h>
#include "mem.h"
#include "simple_list.h"
#include "t_vtx_api.h"
#if defined(USE_SSE_ASM)
/* Build specialized versions of the immediate calls on the fly for
* the current state. ???P4 SSE2 versions???
*/
static struct dynfn *makeSSENormal3fv( struct _vb *vb, int key )
{
/* Requires P4 (sse2?)
*/
static unsigned char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $0x12345678,%edx */
0xf3, 0x0f, 0x7e, 0x00, /* movq (%eax),%xmm0 */
0x66, 0x0f, 0x6e, 0x48, 0x08, /* movd 0x8(%eax),%xmm1 */
0x66, 0x0f, 0xd6, 0x42, 0x0c, /* movq %xmm0,0xc(%edx) */
0x66, 0x0f, 0x7e, 0x4a, 0x14, /* movd %xmm1,0x14(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
insert_at_head( &vb->dfn_cache.Normal3fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)vb->normalptr);
return dfn;
}
void _tnl_InitSSECodegen( struct dfn_generators *gen )
{
/* Need to:
* - check kernel sse support
* - check p4/sse2
*/
(void) makeSSENormal3fv;
}
#else
void _tnl_InitSSECodegen( struct dfn_generators *gen )
{
(void) gen;
}
#endif

727
src/mesa/tnl/t_vtx_x86.c Normal file
View File

@@ -0,0 +1,727 @@
/* $XFree86$ */
/**************************************************************************
Copyright 2002 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
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 <stdio.h>
#include <assert.h>
#include "mem.h"
#include "mmath.h"
#include "simple_list.h"
#include "tnl_vtxfmt.h"
#if defined(USE_X86_ASM)
/* Build specialized versions of the immediate calls on the fly for
* the current state. Generic x86 versions.
*/
struct dynfn *tnl_makeX86Vertex3f( TNLcontext *tnl, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (RADEON_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
switch (tnl->vertex_size) {
case 4: {
static char temp[] = {
0x8b, 0x0d, 0,0,0,0, /* mov DMAPTR,%ecx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x89, 0x01, /* mov %eax,(%ecx) */
0x89, 0x51, 0x04, /* mov %edx,0x4(%ecx) */
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */
0x8b, 0x15, 0,0,0,0, /* mov VERTEX[3],%edx */
0x89, 0x41, 0x08, /* mov %eax,0x8(%ecx) */
0x89, 0x51, 0x0c, /* mov %edx,0xc(%ecx) */
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */
0x83, 0xc1, 0x10, /* add $0x10,%ecx */
0x48, /* dec %eax */
0x89, 0x0d, 0,0,0,0, /* mov %ecx,DMAPTR */
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0,0,0,0 /* jmp *NOTIFY */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 2, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 25, 0x0, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 36, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 46, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 51, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 60, 0x0, (int)&tnl->notify);
break;
}
case 6: {
static char temp[] = {
0x57, /* push %edi */
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */
0x8b, 0x44, 0x24, 0x8, /* mov 0x8(%esp,1),%eax */
0x8b, 0x54, 0x24, 0xc, /* mov 0xc(%esp,1),%edx */
0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */
0x89, 0x07, /* mov %eax,(%edi) */
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */
0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */
0xa1, 0, 0, 0, 0, /* mov VERTEX[3],%eax */
0x8b, 0x15, 0, 0, 0, 0, /* mov VERTEX[4],%edx */
0x8b, 0x0d, 0, 0, 0, 0, /* mov VERTEX[5],%ecx */
0x89, 0x47, 0x0c, /* mov %eax,0xc(%edi) */
0x89, 0x57, 0x10, /* mov %edx,0x10(%edi) */
0x89, 0x4f, 0x14, /* mov %ecx,0x14(%edi) */
0x83, 0xc7, 0x18, /* add $0x18,%edi */
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */
0x48, /* dec %eax */
0x5f, /* pop %edi */
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0,0,0,0, /* jmp *NOTIFY */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 3, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 28, 0x0, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 34, 0x0, (int)&tnl->vertex[4]);
FIXUP(dfn->code, 40, 0x0, (int)&tnl->vertex[5]);
FIXUP(dfn->code, 57, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 63, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 70, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 79, 0x0, (int)&tnl->notify);
break;
}
default: {
/* Repz convenient as it's possible to emit code for any size
* vertex with little tweaking. Might as well read vertsize
* though, and have only one of these.
*/
static char temp[] = {
0x57, /* push %edi */
0x56, /* push %esi */
0xbe, 0, 0, 0, 0, /* mov $VERTEX+3,%esi */
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */
0x8b, 0x44, 0x24, 0x0c, /* mov 0x0c(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x10, /* mov 0x10(%esp,1),%edx */
0x8b, 0x4c, 0x24, 0x14, /* mov 0x14(%esp,1),%ecx */
0x89, 0x07, /* mov %eax,(%edi) */
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */
0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */
0x83, 0xc7, 0x0c, /* add $0xc,%edi */
0xb9, 0, 0, 0, 0, /* mov $VERTSIZE-3,%ecx */
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */
0x48, /* dec %eax */
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */
0x5e, /* pop %esi */
0x5f, /* pop %edi */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-3);
FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
break;
}
}
insert_at_head( &tnl->dfn_cache.Vertex3f, dfn );
dfn->key = key;
return dfn;
}
struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *tnl, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
switch (tnl->vertex_size) {
case 6: {
static char temp[] = {
0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */
0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */
0x8b, 0x11, /* mov (%ecx),%edx */
0x89, 0x10, /* mov %edx,(%eax) */
0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */
0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */
0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */
0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */
0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */
0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */
0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */
0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */
0x83, 0xc0, 0x18, /* add $0x18,%eax */
0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */
0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */
0x48, /* dec %eax */
0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */
0x74, 0x01, /* je 2a4 <.f11> */
0xc3, /* ret */
0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
FIXUP(dfn->code, 45, 0x00000024, (int)&tnl->vertex[5]);
FIXUP(dfn->code, 56, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 61, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 67, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 76, 0x00000008, (int)&tnl->notify);
break;
}
case 8: {
static char temp[] = {
0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */
0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */
0x8b, 0x11, /* mov (%ecx),%edx */
0x89, 0x10, /* mov %edx,(%eax) */
0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */
0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */
0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */
0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */
0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */
0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */
0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */
0x89, 0x48, 0x18, /* mov %ecx,0x18(%eax) */
0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */
0x89, 0x50, 0x1c, /* mov %edx,0x1c(%eax) */
0x83, 0xc0, 0x20, /* add $0x20,%eax */
0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */
0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */
0x48, /* dec %eax */
0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */
0x74, 0x01, /* je 2a4 <.f11> */
0xc3, /* ret */
0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
FIXUP(dfn->code, 45, 0x0000001c, (int)&tnl->vertex[5]);
FIXUP(dfn->code, 51, 0x00000020, (int)&tnl->vertex[6]);
FIXUP(dfn->code, 63, 0x00000024, (int)&tnl->vertex[7]);
FIXUP(dfn->code, 74, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 79, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 85, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 94, 0x00000008, (int)&tnl->notify);
break;
}
default: {
/* Repz convenient as it's possible to emit code for any size
* vertex with little tweaking. Might as well read vertsize
* though, and have only one of these.
*/
static char temp[] = {
0x8b, 0x54, 0x24, 0x04, /* mov 0x4(%esp,1),%edx */
0x57, /* push %edi */
0x56, /* push %esi */
0x8b, 0x3d, 1,1,1,1, /* mov DMAPTR,%edi */
0x8b, 0x02, /* mov (%edx),%eax */
0x8b, 0x4a, 0x04, /* mov 0x4(%edx),%ecx */
0x8b, 0x72, 0x08, /* mov 0x8(%edx),%esi */
0x89, 0x07, /* mov %eax,(%edi) */
0x89, 0x4f, 0x04, /* mov %ecx,0x4(%edi) */
0x89, 0x77, 0x08, /* mov %esi,0x8(%edi) */
0x83, 0xc7, 0x0c, /* add $0xc,%edi */
0xb9, 0x06, 0x00, 0x00, 0x00, /* mov $VERTSIZE-3,%ecx */
0xbe, 0x58, 0x00, 0x00, 0x00, /* mov $VERTEX[3],%esi */
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/
0x89, 0x3d, 1, 1, 1, 1, /* mov %edi,DMAPTR */
0xa1, 2, 2, 2, 2, /* mov COUNTER,%eax */
0x5e, /* pop %esi */
0x5f, /* pop %edi */
0x48, /* dec %eax */
0xa3, 2, 2, 2, 2, /* mov %eax,COUNTER */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 8, 0x01010101, (int)&tnl->dmaptr);
FIXUP(dfn->code, 32, 0x00000006, tnl->vertex_size-3);
FIXUP(dfn->code, 37, 0x00000058, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 45, 0x01010101, (int)&tnl->dmaptr);
FIXUP(dfn->code, 50, 0x02020202, (int)&tnl->counter);
FIXUP(dfn->code, 58, 0x02020202, (int)&tnl->counter);
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
break;
}
}
insert_at_head( &tnl->dfn_cache.Vertex3fv, dfn );
dfn->key = key;
return dfn;
}
struct dynfn *tnl_makeX86Normal3fv( TNLcontext *tnl, int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0, 0, 0, 0, /* mov $DEST,%edx */
0x8b, 0x08, /* mov (%eax),%ecx */
0x89, 0x0a, /* mov %ecx,(%edx) */
0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */
0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */
0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.Normal3fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr);
return dfn;
}
struct dynfn *tnl_makeX86Normal3f( TNLcontext *tnl, int key )
{
static char temp[] = {
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */
0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.Normal3f, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr);
return dfn;
}
struct dynfn *tnl_makeX86Color4ubv( TNLcontext *tnl, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
insert_at_head( &tnl->dfn_cache.Color4ubv, dfn );
dfn->key = key;
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
if (key & TNL_CP_VC_FRMT_PKCOLOR) {
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x00, /* mov (%eax),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0xc3, /* ret */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->ubytecolorptr);
return dfn;
}
else {
static char temp[] = {
0x53, /* push %ebx */
0xba, 0x00, 0x00, 0x00, 0x00, /* mov $0x0,%edx */
0x31, 0xc0, /* xor %eax,%eax */
0x31, 0xc9, /* xor %ecx,%ecx */
0x8b, 0x5c, 0x24, 0x08, /* mov 0x8(%esp,1), %ebx */
0x8b, 0x1b, /* mov (%ebx), %ebx */
0x88, 0xd8, /* mov %bl, %al */
0x88, 0xf9, /* mov %bh, %cl */
0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */
0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */
0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */
0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */
0x31, 0xc0, /* xor %eax,%eax */
0x31, 0xc9, /* xor %ecx,%ecx */
0xc1, 0xeb, 0x10, /* shr $0x10, %ebx */
0x88, 0xd8, /* mov %bl, %al */
0x88, 0xf9, /* mov %bh, %cl */
0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */
0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */
0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */
0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */
0x5b, /* pop %ebx */
0xc3, /* ret */
};
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab);
FIXUP(dfn->code, 27, 0xdeadbeaf, (int)tnl->floatcolorptr);
FIXUP(dfn->code, 33, 0xdeadbeaf, (int)tnl->floatcolorptr+4);
FIXUP(dfn->code, 55, 0xdeadbeaf, (int)tnl->floatcolorptr+8);
FIXUP(dfn->code, 61, 0xdeadbeaf, (int)tnl->floatcolorptr+12);
return dfn;
}
}
struct dynfn *tnl_makeX86Color4ub( TNLcontext *tnl, int key )
{
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
if (key & TNL_CP_VC_FRMT_PKCOLOR) {
/* XXX push/pop */
static char temp[] = {
0x53, /* push %ebx */
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x0c, /* mov 0xc(%esp,1),%edx */
0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */
0x8b, 0x5c, 0x24, 0x14, /* mov 0x14(%esp,1),%ebx */
0xa2, 0, 0, 0, 0, /* mov %al,DEST */
0x88, 0x15, 0, 0, 0, 0, /* mov %dl,DEST+1 */
0x88, 0x0d, 0, 0, 0, 0, /* mov %cl,DEST+2 */
0x88, 0x1d, 0, 0, 0, 0, /* mov %bl,DEST+3 */
0x5b, /* pop %ebx */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
insert_at_head( &tnl->dfn_cache.Color4ub, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 18, 0x0, (int)tnl->ubytecolorptr);
FIXUP(dfn->code, 24, 0x0, (int)tnl->ubytecolorptr+1);
FIXUP(dfn->code, 30, 0x0, (int)tnl->ubytecolorptr+2);
FIXUP(dfn->code, 36, 0x0, (int)tnl->ubytecolorptr+3);
return dfn;
}
else
return 0;
}
struct dynfn *tnl_makeX86Color3fv( TNLcontext *tnl, int key )
{
if (key & (TNL_CP_VC_FRMT_PKCOLOR|TNL_CP_VC_FRMT_FPALPHA))
return 0;
else
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0, 0, 0, 0, /* mov $DEST,%edx */
0x8b, 0x08, /* mov (%eax),%ecx */
0x89, 0x0a, /* mov %ecx,(%edx) */
0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */
0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */
0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.Color3fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)tnl->floatcolorptr);
return dfn;
}
}
struct dynfn *tnl_makeX86Color3f( TNLcontext *tnl, int key )
{
if (key & (TNL_CP_VC_FRMT_PKCOLOR|TNL_CP_VC_FRMT_FPALPHA))
return 0;
else
{
static char temp[] = {
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */
0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.Color3f, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->floatcolorptr);
return dfn;
}
}
struct dynfn *tnl_makeX86TexCoord2fv( TNLcontext *tnl, int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x08, /* mov (%eax),%ecx */
0x8b, 0x40, 0x04, /* mov 0x4(%eax),%eax */
0x89, 0x0a, /* mov %ecx,(%edx) */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]);
return dfn;
}
struct dynfn *tnl_makeX86TexCoord2f( TNLcontext *tnl, int key )
{
static char temp[] = {
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x89, 0x02, /* mov %eax,(%edx) */
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]);
return dfn;
}
struct dynfn *tnl_makeX86MultiTexCoord2fvARB( TNLcontext *tnl, int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x11, /* mov (%ecx),%edx */
0xc1, 0xe0, 0x03, /* shl $0x3,%eax */
0x8b, 0x49, 0x04, /* mov 0x4(%ecx),%ecx */
0x89, 0x90, 0, 0, 0, 0,/* mov %edx,DEST(%eax) */
0x89, 0x88, 0, 0, 0, 0,/* mov %ecx,DEST+8(%eax) */
0xc3, /* ret */
};
static char temp2[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x14, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%edx */
0x8b, 0x01, /* mov (%ecx),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0x8b, 0x41, 0x04, /* mov 0x4(%ecx),%eax */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.MultiTexCoord2fvARB, dfn );
dfn->key = key;
if ((key & (TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) ==
(TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) {
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 26, 0x0, (int)tnl->texcoordptr[0]);
FIXUP(dfn->code, 32, 0x0, (int)tnl->texcoordptr[0]+4);
} else {
dfn->code = ALIGN_MALLOC( sizeof(temp2), 16 );
memcpy (dfn->code, temp2, sizeof(temp2));
FIXUP(dfn->code, 19, 0x0, (int)tnl->texcoordptr);
}
return dfn;
}
struct dynfn *tnl_makeX86MultiTexCoord2fARB( TNLcontext *tnl,
int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0xc1, 0xe0, 0x03, /* shl $0x3,%eax */
0x89, 0x90, 0, 0, 0, 0, /* mov %edx,DEST(%eax) */
0x89, 0x88, 0, 0, 0, 0, /* mov %ecx,DEST+8(%eax) */
0xc3, /* ret */
};
static char temp2[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x04, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%eax */
0x89, 0x10, /* mov %edx,(%eax) */
0x89, 0x48, 0x04, /* mov %ecx,0x4(%eax) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (TNL_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
insert_at_head( &tnl->dfn_cache.MultiTexCoord2fARB, dfn );
dfn->key = key;
if ((key & (TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) ==
(TNL_CP_VC_FRMT_ST0|TNL_CP_VC_FRMT_ST1)) {
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 25, 0x0, (int)tnl->texcoordptr[0]);
FIXUP(dfn->code, 31, 0x0, (int)tnl->texcoordptr[0]+4);
}
else {
/* Note: this might get generated multiple times, even though the
* actual emitted code is the same.
*/
dfn->code = ALIGN_MALLOC( sizeof(temp2), 16 );
memcpy (dfn->code, temp2, sizeof(temp2));
FIXUP(dfn->code, 23, 0x0, (int)tnl->texcoordptr);
}
return dfn;
}
void _tnl_InitX86Codegen( struct dfn_generators *gen )
{
gen->Vertex3f = tnl_makeX86Vertex3f;
gen->Vertex3fv = tnl_makeX86Vertex3fv;
gen->Color4ub = tnl_makeX86Color4ub; /* PKCOLOR only */
gen->Color4ubv = tnl_makeX86Color4ubv; /* PKCOLOR only */
gen->Normal3f = tnl_makeX86Normal3f;
gen->Normal3fv = tnl_makeX86Normal3fv;
gen->TexCoord2f = tnl_makeX86TexCoord2f;
gen->TexCoord2fv = tnl_makeX86TexCoord2fv;
gen->MultiTexCoord2fARB = tnl_makeX86MultiTexCoord2fARB;
gen->MultiTexCoord2fvARB = tnl_makeX86MultiTexCoord2fvARB;
gen->Color3f = tnl_makeX86Color3f;
gen->Color3fv = tnl_makeX86Color3fv;
/* Not done:
*/
/* gen->Vertex2f = tnl_makeX86Vertex2f; */
/* gen->Vertex2fv = tnl_makeX86Vertex2fv; */
/* gen->Color3ub = tnl_makeX86Color3ub; */
/* gen->Color3ubv = tnl_makeX86Color3ubv; */
/* gen->Color4f = tnl_makeX86Color4f; */
/* gen->Color4fv = tnl_makeX86Color4fv; */
/* gen->TexCoord1f = tnl_makeX86TexCoord1f; */
/* gen->TexCoord1fv = tnl_makeX86TexCoord1fv; */
/* gen->MultiTexCoord1fARB = tnl_makeX86MultiTexCoord1fARB; */
/* gen->MultiTexCoord1fvARB = tnl_makeX86MultiTexCoord1fvARB; */
}
#else
void _tnl_InitX86Codegen( struct dfn_generators *gen )
{
(void) gen;
}
#endif