First round of codegen for t_vtx_api.c -- ie the Begin/Vertex/End code.

Enable with env var:  MESA_CODEGEN=t.
This commit is contained in:
Keith Whitwell 2004-03-29 11:05:02 +00:00
parent 638ea113b9
commit c8100a02d2
6 changed files with 496 additions and 643 deletions

View File

@ -132,6 +132,8 @@ TNL_SOURCES = \
tnl/t_vb_vertex.c \
tnl/t_vertex.c \
tnl/t_vtx_api.c \
tnl/t_vtx_generic.c \
tnl/t_vtx_x86.c \
tnl/t_vtx_eval.c \
tnl/t_vtx_exec.c
@ -159,7 +161,8 @@ X86_SOURCES = \
x86/sse_xform2.S \
x86/sse_xform3.S \
x86/sse_xform4.S \
x86/sse_normal.S
x86/sse_normal.S \
tnl/t_vtx_x86_gcc.S
SPARC_SOURCES = \
sparc/clip.S \

View File

@ -121,6 +121,10 @@ _tnl_CreateContext( GLcontext *ctx )
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables;
if (getenv("MESA_CODEGEN"))
tnl->AllowCodegen = GL_TRUE;
return GL_TRUE;
}

View File

@ -248,10 +248,28 @@ struct tnl_copied_vtx {
#define VERT_BUFFER_SIZE 2048 /* 8kbytes */
#define ERROR_ATTRIB _TNL_ATTRIB_MAX /* error path for t_vtx_api.c */
typedef void (*attrfv_func)( const GLfloat * );
struct dynfn {
struct dynfn *next, *prev;
int key;
char *code;
};
struct dynfn_lists {
struct dynfn Vertex[4];
struct dynfn Attribute[4];
};
struct dynfn_generators {
struct dynfn *(*Vertex[4])( GLcontext *ctx, int key );
struct dynfn *(*Attribute[4])( GLcontext *ctx, int key );
};
#define _TNL_MAX_ATTR_CODEGEN 16
/* The assembly of vertices in immediate mode is separated from
* display list compilation. This allows a simpler immediate mode
* treatment and a display list compiler better suited to
@ -269,7 +287,12 @@ struct tnl_vtx {
GLfloat *current[_TNL_ATTRIB_MAX]; /* points into ctx->Current, etc */
GLuint counter, initial_counter;
struct tnl_copied_vtx copied;
attrfv_func tabfv[_TNL_ATTRIB_MAX+1][4]; /* +1 for ERROR_ATTRIB */
attrfv_func tabfv[_TNL_MAX_ATTR_CODEGEN+1][4]; /* plus 1 for ERROR_ATTRIB */
struct dynfn_lists cache;
struct dynfn_generators gen;
struct tnl_eval eval;
GLboolean *edgeflag_tmp;
GLboolean have_materials;
@ -714,6 +737,7 @@ typedef struct
GLboolean IsolateMaterials;
GLboolean AllowVertexFog;
GLboolean AllowPixelFog;
GLboolean AllowCodegen;
GLboolean _DoVertexFog; /* eval fog function at each vertex? */

View File

@ -41,9 +41,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "api_arrayelt.h"
#include "api_noop.h"
#include "t_vtx_api.h"
#include "simple_list.h"
static void reset_attrfv( TNLcontext *tnl );
static void init_attrfv( TNLcontext *tnl );
static attrfv_func choose[_TNL_MAX_ATTR_CODEGEN+1][4]; /* +1 for ERROR_ATTRIB */
static attrfv_func generic_attr_func[_TNL_MAX_ATTR_CODEGEN][4];
/* Close off the last primitive, execute the buffer, restart the
@ -100,7 +103,7 @@ static void _tnl_wrap_buffers( GLcontext *ctx )
/* Deal with buffer wrapping where provoked by the vertex buffer
* filling up, as opposed to upgrade_vertex().
*/
static void _tnl_wrap_filled_vertex( GLcontext *ctx )
void _tnl_wrap_filled_vertex( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLfloat *data = tnl->vtx.copied.buffer;
@ -156,7 +159,8 @@ static void _tnl_copy_to_current( GLcontext *ctx )
/* Colormaterial -- this kindof sucks.
*/
if (ctx->Light.ColorMaterialEnabled) {
_mesa_update_color_material(ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
_mesa_update_color_material(ctx,
ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
}
if (tnl->vtx.have_materials) {
@ -204,7 +208,6 @@ static void _tnl_wrap_upgrade_vertex( GLcontext *ctx,
GLfloat *tmp;
GLint lastcount = tnl->vtx.initial_counter - tnl->vtx.counter;
/* Run pipeline on current vertices, copy wrapped vertices
* to tnl->vtx.copied.
*/
@ -222,10 +225,10 @@ static void _tnl_wrap_upgrade_vertex( GLcontext *ctx,
* begin/end so that they don't bloat the vertices.
*/
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
tnl->vtx.attrsz[attr] == 0
&& lastcount > 8
) {
init_attrfv( tnl );
tnl->vtx.attrsz[attr] == 0 &&
lastcount > 8 &&
tnl->vtx.vertex_size) {
reset_attrfv( tnl );
}
/* Fix up sizes:
@ -289,6 +292,19 @@ static void _tnl_wrap_upgrade_vertex( GLcontext *ctx,
tnl->vtx.counter -= tnl->vtx.copied.nr;
tnl->vtx.copied.nr = 0;
}
/* For codegen - attrptr's may have changed, so need to redo
* codegen. Might be a reasonable place to try & detect attributes
* in the vertex which aren't being submitted any more.
*/
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
if (tnl->vtx.attrsz[i]) {
GLuint j = tnl->vtx.attrsz[i] - 1;
if (i < _TNL_MAX_ATTR_CODEGEN)
tnl->vtx.tabfv[i][j] = choose[i][j];
}
}
@ -314,146 +330,131 @@ static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz )
}
static struct dynfn *lookup( struct dynfn *l, GLuint key )
{
struct dynfn *f;
foreach( f, l ) {
if (f->key == key)
return f;
}
return 0;
}
static attrfv_func do_codegen( GLcontext *ctx, GLuint attr, GLuint sz )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct dynfn *dfn = 0;
if (attr == 0) {
GLuint key = tnl->vtx.vertex_size;
dfn = lookup( &tnl->vtx.cache.Vertex[sz-1], key );
if (!dfn)
dfn = tnl->vtx.gen.Vertex[sz-1]( ctx, key );
}
else {
GLuint key = (GLuint) tnl->vtx.attrptr[attr];
dfn = lookup( &tnl->vtx.cache.Attribute[sz-1], key );
if (!dfn)
dfn = tnl->vtx.gen.Attribute[sz-1]( ctx, key );
}
if (dfn)
return (attrfv_func) dfn->code;
else
return 0;
}
/* Helper function for 'CHOOSE' macro. Do what's necessary when an
* entrypoint is called for the first time.
*/
static void do_choose( GLuint attr, GLuint sz,
void (*fallback_attr_func)( const GLfloat *),
void (*choose1)( const GLfloat *),
void (*choose2)( const GLfloat *),
void (*choose3)( const GLfloat *),
void (*choose4)( const GLfloat *),
const GLfloat *v )
static attrfv_func do_choose( GLuint attr, GLuint sz )
{
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint oldsz = tnl->vtx.attrsz[attr];
if (tnl->vtx.attrsz[attr] != sz)
assert(attr < _TNL_MAX_ATTR_CODEGEN);
if (oldsz != sz) {
/* Reset any active pointers for this attribute
*/
if (oldsz)
tnl->vtx.tabfv[attr][oldsz-1] = choose[attr][oldsz-1];
_tnl_fixup_vertex( ctx, attr, sz );
/* Does this belong here? Necessitates resetting vtxfmt on each
* flush (otherwise flags won't get reset afterwards).
*/
if (attr == 0)
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
/* Does setting NeedFlush belong here? Necessitates resetting
* vtxfmt on each flush (otherwise flags won't get reset
* afterwards).
*/
if (attr == 0)
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
else
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
}
/* Try to use codegen:
*/
if (tnl->AllowCodegen)
tnl->vtx.tabfv[attr][sz-1] = do_codegen( ctx, attr, sz );
else
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
tnl->vtx.tabfv[attr][sz-1] = 0;
/* Reset any active pointers for this attribute
/* Else use generic version:
*/
tnl->vtx.tabfv[attr][0] = choose1;
tnl->vtx.tabfv[attr][1] = choose2;
tnl->vtx.tabfv[attr][2] = choose3;
tnl->vtx.tabfv[attr][3] = choose4;
if (!tnl->vtx.tabfv[attr][sz-1])
tnl->vtx.tabfv[attr][sz-1] = generic_attr_func[attr][sz-1];
/* Update the secondary dispatch table with the new function
*/
tnl->vtx.tabfv[attr][sz-1] = fallback_attr_func;
(*fallback_attr_func)(v);
return tnl->vtx.tabfv[attr][sz-1];
}
/* 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 choose_##ATTR##_##N( const GLfloat *v ); \
\
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 CHOOSE( ATTR, N ) \
static void choose_##ATTR##_##N( const GLfloat *v ) \
{ \
do_choose(ATTR, N, \
attrib_##ATTR##_##N, \
choose_##ATTR##_1, \
choose_##ATTR##_2, \
choose_##ATTR##_3, \
choose_##ATTR##_4, \
v ); \
attrfv_func f = do_choose(ATTR, N); \
f( v ); \
}
#define INIT(ATTR) \
static void init_##ATTR( TNLcontext *tnl ) \
{ \
tnl->vtx.tabfv[ATTR][0] = choose_##ATTR##_1; \
tnl->vtx.tabfv[ATTR][1] = choose_##ATTR##_2; \
tnl->vtx.tabfv[ATTR][2] = choose_##ATTR##_3; \
tnl->vtx.tabfv[ATTR][3] = choose_##ATTR##_4; \
}
#define ATTRS( ATTRIB ) \
ATTRFV( ATTRIB, 1 ) \
ATTRFV( ATTRIB, 2 ) \
ATTRFV( ATTRIB, 3 ) \
ATTRFV( ATTRIB, 4 ) \
#define CHOOSERS( ATTRIB ) \
CHOOSE( ATTRIB, 1 ) \
CHOOSE( ATTRIB, 2 ) \
CHOOSE( ATTRIB, 3 ) \
CHOOSE( ATTRIB, 4 ) \
INIT( ATTRIB ) \
/* Generate a lot of functions. These are the actual worker
* functions, which are equivalent to those generated via codegen
* elsewhere.
*/
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 )
#define INIT_CHOOSERS(ATTR) \
choose[ATTR][0] = choose_##ATTR##_1; \
choose[ATTR][1] = choose_##ATTR##_2; \
choose[ATTR][2] = choose_##ATTR##_3; \
choose[ATTR][3] = choose_##ATTR##_4;
CHOOSERS( 0 )
CHOOSERS( 1 )
CHOOSERS( 2 )
CHOOSERS( 3 )
CHOOSERS( 4 )
CHOOSERS( 5 )
CHOOSERS( 6 )
CHOOSERS( 7 )
CHOOSERS( 8 )
CHOOSERS( 9 )
CHOOSERS( 10 )
CHOOSERS( 11 )
CHOOSERS( 12 )
CHOOSERS( 13 )
CHOOSERS( 14 )
CHOOSERS( 15 )
static void error_attrib( const GLfloat *unused )
{
@ -462,326 +463,25 @@ static void error_attrib( const GLfloat *unused )
_mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib" );
}
static void init_error_attrib( TNLcontext *tnl )
{
tnl->vtx.tabfv[ERROR_ATTRIB][0] = error_attrib;
tnl->vtx.tabfv[ERROR_ATTRIB][1] = error_attrib;
tnl->vtx.tabfv[ERROR_ATTRIB][2] = error_attrib;
tnl->vtx.tabfv[ERROR_ATTRIB][3] = error_attrib;
}
static void init_attrfv( TNLcontext *tnl )
static void reset_attrfv( TNLcontext *tnl )
{
if (tnl->vtx.vertex_size) {
GLuint i;
init_0( tnl );
init_1( tnl );
init_2( tnl );
init_3( tnl );
init_4( tnl );
init_5( tnl );
init_6( tnl );
init_7( tnl );
init_8( tnl );
init_9( tnl );
init_10( tnl );
init_11( tnl );
init_12( tnl );
init_13( tnl );
init_14( tnl );
init_15( tnl );
init_error_attrib( tnl );
GLuint i;
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
if (tnl->vtx.attrsz[i]) {
GLuint j = tnl->vtx.attrsz[i] - 1;
tnl->vtx.attrsz[i] = 0;
tnl->vtx.vertex_size = 0;
tnl->vtx.have_materials = 0;
}
}
/* 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 enum_error( void )
{
GET_CURRENT_CONTEXT( ctx );
_mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib" );
}
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 );
if (i < _TNL_MAX_ATTR_CODEGEN)
tnl->vtx.tabfv[i][j] = choose[i][j];
}
tnl->vtx.vertex_size = 0;
tnl->vtx.have_materials = 0;
}
/* Materials:
@ -797,35 +497,33 @@ static void GLAPIENTRY _tnl_VertexAttrib4fvNV( GLuint index,
*
* There is no aliasing of material attributes with other entrypoints.
*/
#define MAT_ATTR( A, N, params ) \
#define OTHER_ATTR( A, N, params ) \
do { \
if (tnl->vtx.attrsz[A] != N) { \
_tnl_fixup_vertex( ctx, A, N ); \
tnl->vtx.have_materials = GL_TRUE; \
} \
\
{ \
GLfloat *dest = tnl->vtx.attrptr[A]; \
if (N>0) dest[0] = params[0]; \
if (N>1) dest[1] = params[1]; \
if (N>2) dest[2] = params[2]; \
if (N>3) dest[3] = params[3]; \
if (N>0) dest[0] = (params)[0]; \
if (N>1) dest[1] = (params)[1]; \
if (N>2) dest[2] = (params)[2]; \
if (N>3) dest[3] = (params)[3]; \
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
} \
} while (0)
#define MAT( ATTR, N, face, params ) \
do { \
if (face != GL_BACK) \
MAT_ATTR( ATTR, N, params ); /* front */ \
if (face != GL_FRONT) \
MAT_ATTR( ATTR + 1, N, params ); /* back */ \
#define MAT( ATTR, N, face, params ) \
do { \
if (face != GL_BACK) \
OTHER_ATTR( ATTR, N, params ); /* front */ \
if (face != GL_FRONT) \
OTHER_ATTR( ATTR + 1, N, params ); /* back */ \
} while (0)
/* NOTE: Have to remove/deal-with colormaterial crossovers, probably
* later on - in the meantime just store everything.
/* Colormaterial is dealt with later on.
*/
static void GLAPIENTRY _tnl_Materialfv( GLenum face, GLenum pname,
const GLfloat *params )
@ -871,44 +569,43 @@ static void GLAPIENTRY _tnl_Materialfv( GLenum face, GLenum pname,
_mesa_error( ctx, GL_INVALID_ENUM, "glMaterialfv" );
return;
}
tnl->vtx.have_materials = GL_TRUE;
}
#define IDX_ATTR( A, IDX ) \
do { \
GET_CURRENT_CONTEXT( ctx ); \
TNLcontext *tnl = TNL_CONTEXT(ctx); \
\
if (tnl->vtx.attrsz[A] != 1) { \
_tnl_fixup_vertex( ctx, A, 1 ); \
} \
\
{ \
GLfloat *dest = tnl->vtx.attrptr[A]; \
dest[0] = IDX; \
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
} \
} while (0)
static void GLAPIENTRY _tnl_EdgeFlag( GLboolean b )
{
IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)b );
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLfloat f = (GLfloat)b;
OTHER_ATTR( _TNL_ATTRIB_EDGEFLAG, 1, &f );
}
static void GLAPIENTRY _tnl_EdgeFlagv( const GLboolean *v )
{
IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)v[0] );
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLfloat f = (GLfloat)v[0];
OTHER_ATTR( _TNL_ATTRIB_EDGEFLAG, 1, &f );
}
static void GLAPIENTRY _tnl_Indexf( GLfloat f )
{
IDX_ATTR( _TNL_ATTRIB_INDEX, f );
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
OTHER_ATTR( _TNL_ATTRIB_INDEX, 1, &f );
}
static void GLAPIENTRY _tnl_Indexfv( const GLfloat *v )
{
IDX_ATTR( _TNL_ATTRIB_INDEX, v[0] );
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
OTHER_ATTR( _TNL_ATTRIB_INDEX, 1, v );
}
/* Eval
@ -1029,7 +726,8 @@ static void GLAPIENTRY _tnl_Begin( GLenum mode )
if (ctx->NewState) {
_mesa_update_state( ctx );
if (!(tnl->Driver.NotifyBegin && tnl->Driver.NotifyBegin( ctx, mode )))
if (!(tnl->Driver.NotifyBegin &&
tnl->Driver.NotifyBegin( ctx, mode )))
ctx->Exec->Begin(mode);
return;
}
@ -1086,14 +784,11 @@ static void GLAPIENTRY _tnl_End( void )
static void _tnl_exec_vtxfmt_init( GLcontext *ctx )
{
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt);
vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
vfmt->Begin = _tnl_Begin;
vfmt->CallList = _mesa_CallList;
vfmt->CallLists = _mesa_CallLists;
vfmt->Color3f = _tnl_Color3f;
vfmt->Color3fv = _tnl_Color3fv;
vfmt->Color4f = _tnl_Color4f;
vfmt->Color4fv = _tnl_Color4fv;
vfmt->EdgeFlag = _tnl_EdgeFlag;
vfmt->EdgeFlagv = _tnl_EdgeFlagv;
vfmt->End = _tnl_End;
@ -1103,45 +798,9 @@ static void _tnl_exec_vtxfmt_init( GLcontext *ctx )
vfmt->EvalCoord2fv = _tnl_EvalCoord2fv;
vfmt->EvalPoint1 = _tnl_EvalPoint1;
vfmt->EvalPoint2 = _tnl_EvalPoint2;
vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
vfmt->Indexf = _tnl_Indexf;
vfmt->Indexfv = _tnl_Indexfv;
vfmt->Materialfv = _tnl_Materialfv;
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;
vfmt->Rectf = _mesa_noop_Rectf;
vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
@ -1161,13 +820,9 @@ void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
_tnl_flush_vtx( ctx );
}
{
if (tnl->vtx.vertex_size) {
_tnl_copy_to_current( ctx );
/* reset attrfv table
*/
init_attrfv( tnl );
flags |= FLUSH_UPDATE_CURRENT;
reset_attrfv( tnl );
}
ctx->Driver.NeedFlush = 0;
@ -1191,26 +846,92 @@ static void _tnl_current_init( GLcontext *ctx )
tnl->vtx.current[_TNL_ATTRIB_INDEX] = &ctx->Current.Index;
}
static struct dynfn *no_codegen( GLcontext *ctx, int key )
{
return 0;
}
void _tnl_vtx_init( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct tnl_vertex_arrays *tmp = &tnl->vtx_inputs;
GLuint i;
static int firsttime = 1;
if (firsttime) {
firsttime = 0;
INIT_CHOOSERS( 0 );
INIT_CHOOSERS( 1 );
INIT_CHOOSERS( 2 );
INIT_CHOOSERS( 3 );
INIT_CHOOSERS( 4 );
INIT_CHOOSERS( 5 );
INIT_CHOOSERS( 6 );
INIT_CHOOSERS( 7 );
INIT_CHOOSERS( 8 );
INIT_CHOOSERS( 9 );
INIT_CHOOSERS( 10 );
INIT_CHOOSERS( 11 );
INIT_CHOOSERS( 12 );
INIT_CHOOSERS( 13 );
INIT_CHOOSERS( 14 );
INIT_CHOOSERS( 15 );
choose[ERROR_ATTRIB][0] = error_attrib;
choose[ERROR_ATTRIB][1] = error_attrib;
choose[ERROR_ATTRIB][2] = error_attrib;
choose[ERROR_ATTRIB][3] = error_attrib;
_tnl_generic_attr_table_init( generic_attr_func );
}
for (i = 0; i < _TNL_ATTRIB_INDEX; i++)
_mesa_vector4f_init( &tmp->Attribs[i], 0, 0);
for (i = 0; i < 4; i++) {
make_empty_list( &tnl->vtx.cache.Vertex[i] );
make_empty_list( &tnl->vtx.cache.Attribute[i] );
tnl->vtx.gen.Vertex[i] = no_codegen;
tnl->vtx.gen.Attribute[i] = no_codegen;
}
_tnl_InitX86Codegen( &tnl->vtx.gen );
_tnl_current_init( ctx );
_tnl_exec_vtxfmt_init( ctx );
_tnl_generic_exec_vtxfmt_init( ctx );
_mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt );
tnl->vtx.vertex_size = 1; init_attrfv( tnl );
memcpy( tnl->vtx.tabfv, choose, sizeof(choose) );
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
tnl->vtx.attrsz[i] = 0;
tnl->vtx.vertex_size = 0;
tnl->vtx.have_materials = 0;
}
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 );
}
}
void _tnl_vtx_destroy( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
for (i = 0; i < 4; i++) {
free_funcs( &tnl->vtx.cache.Vertex[i] );
free_funcs( &tnl->vtx.cache.Attribute[i] );
}
}

View File

@ -37,12 +37,23 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "t_context.h"
#define ERROR_ATTRIB 16
/* t_vtx_api.c:
*/
extern void _tnl_vtx_init( GLcontext *ctx );
extern void _tnl_vtx_destroy( GLcontext *ctx );
extern void _tnl_FlushVertices( GLcontext *ctx, GLuint flags );
extern void _tnl_flush_vtx( GLcontext *ctx );
extern void _tnl_wrap_filled_vertex( GLcontext *ctx );
/* t_vtx_exec.c:
*/
extern void _tnl_do_EvalCoord2f( GLcontext* ctx, GLfloat u, GLfloat v );
extern void _tnl_do_EvalCoord1f(GLcontext* ctx, GLfloat u);
extern void _tnl_update_eval( GLcontext *ctx );
@ -55,4 +66,19 @@ extern GLboolean *_tnl_translate_edgeflag( GLcontext *ctx,
extern GLboolean *_tnl_import_current_edgeflag( GLcontext *ctx,
GLuint count );
/* t_vtx_generic.c:
*/
extern void _tnl_generic_exec_vtxfmt_init( GLcontext *ctx );
extern void _tnl_generic_attr_table_init( attrfv_func (*tab)[4] );
/* t_vtx_x86.c:
*/
extern void _tnl_InitX86Codegen( struct dynfn_generators *gen );
#endif

View File

@ -25,9 +25,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#define GLOBL( x ) \
.globl x; \
@ -36,113 +38,127 @@ x:
.data
.align 4
// Someone who knew a lot about this sort of thing would use this
// macro to note current offsets, etc in a special region of the
// object file & just make everything work out neat. I don't know
// enough to do that...
#define SUBST( x ) (0x10101010 + x)
GLOBL ( _x86_Vertex1fv )
;; v already in eax
movl 4(%esp), %ecx
push %edi
push %esi
movl (0x0), %edi ; load vbptr
movl (%eax), %edx ; load v[0]
movl %edx, (%edi) ; vbptr[0] = v[0]
addl $4, %edi ; vbptr += 1
movl $0x0, %ecx ; vertex_size - 1
movl $0x0, %esi ; tnl->vtx.vertex + 1
movl SUBST(0), %edi // 0x0 --> tnl->vtx.vbptr
movl (%ecx), %edx // load v[0]
movl %edx, (%edi) // tnl->vtx.vbptr[0] = v[0]
addl $4, %edi // tnl->vtx.vbptr += 1
movl $SUBST(1), %ecx // 0x1 --> (tnl->vtx.vertex_size - 1)
movl $SUBST(2), %esi // 0x2 --> (tnl->vtx.vertex + 1)
repz
movsl %ds:(%esi), %es:(%edi)
movl %edi, (0) ; save vbptr
movl (0), %edx ; load counter
movsl %ds:(%esi), %es:(%edi)
movl %edi, SUBST(0) // 0x0 --> tnl->vtx.vbptr
movl SUBST(3), %edx // 0x3 --> counter
pop %esi
pop %edi
dec %edx ; counter--
movl %edx, (0) ; save counter
je .5 ; if (counter != 0)
ret ; return
.5: jmp *0 ; else notify();
dec %edx // counter--
movl %edx, SUBST(3) // 0x3 --> counter
je .5 // if (counter != 0)
ret // return
.5: mov $SUBST(4), %eax // else notify()
jmp *%eax // jmp $0x10101014 doesn't seem to work
GLOBL ( _x86_Vertex1fv_end )
.align 4
GLOBL ( _x86_Vertex2fv )
;; v already in eax
movl 4(%esp), %ecx
push %edi
push %esi
movl (0x0), %edi ; load vbptr
movl (%eax), %edx ; load v[0]
movl 4(%eax), %ecx ; load v[1]
movl %edx, (%edi) ; vbptr[0] = v[0]
movl %ecx, 4(%edi) ; vbptr[1] = v[1]
addl $8, %edi ; vbptr += 2
movl $0x0, %ecx ; vertex_size - 2
movl $0x0, %esi ; tnl->vtx.vertex + 2
movl SUBST(0), %edi // load tnl->vtx.vbptr
movl (%ecx), %edx // load v[0]
movl 4(%ecx), %eax // load v[1]
movl %edx, (%edi) // tnl->vtx.vbptr[0] = v[0]
movl %eax, 4(%edi) // tnl->vtx.vbptr[1] = v[1]
addl $8, %edi // tnl->vtx.vbptr += 2
movl $SUBST(1), %ecx // vertex_size - 2
movl $SUBST(2), %esi // tnl->vtx.vertex + 2
repz
movsl %ds:(%esi), %es:(%edi)
movl %edi, (0) ; save vbptr
movl (0), %edx ; load counter
movl %edi, SUBST(0) // save tnl->vtx.vbptr
movl SUBST(3), %edx // load counter
pop %esi
pop %edi
dec %edx ; counter--
movl %edx, (0) ; save counter
je .6 ; if (counter != 0)
ret ; return
.6: jmp *0 ; else notify();
GLOBL ( _x86_Vertex3fv_end )
dec %edx // counter--
movl %edx, SUBST(3) // save counter
je .6 // if (counter != 0)
ret // return
.6: mov $SUBST(4), %eax // else notify()
jmp *%eax // jmp $0x10101014 doesn't seem to work
GLOBL ( _x86_Vertex2fv_end )
.align 4
GLOBL ( _x86_Vertex3fv )
;; v already in eax
movl 4(%esp), %ecx
push %edi
push %esi
movl (0x0), %edi ; load vbptr
movl (%eax), %edx ; load v[0]
movl 4(%eax), %ecx ; load v[1]
movl 8(%eax), %esi ; load v[2]
movl %edx, (%edi) ; vbptr[0] = v[0]
movl %ecx, 4(%edi) ; vbptr[1] = v[1]
movl %esi, 8(%edi) ; vbptr[2] = v[2]
addl $12, %edi ; vbptr += 3
movl $0x0, %ecx ; vertex_size - 3
movl $0x0, %esi ; tnl->vtx.vertex + 3
movl SUBST(0), %edi // load tnl->vtx.vbptr
movl (%ecx), %edx // load v[0]
movl 4(%ecx), %eax // load v[1]
movl 8(%ecx), %esi // load v[2]
movl %edx, (%edi) // tnl->vtx.vbptr[0] = v[0]
movl %eax, 4(%edi) // tnl->vtx.vbptr[1] = v[1]
movl %esi, 8(%edi) // tnl->vtx.vbptr[2] = v[2]
addl $12, %edi // tnl->vtx.vbptr += 3
movl $SUBST(1), %ecx // vertex_size - 3
movl $SUBST(2), %esi // tnl->vtx.vertex + 3
repz
movsl %ds:(%esi), %es:(%edi)
movl %edi, (0) ; save vbptr
movl (0), %edx ; load counter
movl %edi, SUBST(0) // save tnl->vtx.vbptr
movl SUBST(3), %edx // load counter
pop %esi
pop %edi
dec %edx ; counter--
movl %edx, (0) ; save counter
je .7 ; if (counter != 0)
ret ; return
.7: jmp *0 ; else notify();
dec %edx // counter--
movl %edx, SUBST(3) // save counter
je .7 // if (counter != 0)
ret // return
.7: mov $SUBST(4), %eax // else notify()
jmp *%eax // jmp $0x10101014 doesn't seem to work
GLOBL ( _x86_Vertex3fv_end )
.align 4
GLOBL ( _x86_Vertex4fv )
;; v already in eax
movl 4(%esp), %ecx
push %edi
push %esi
movl (0x0), %edi ; load vbptr
movl (%eax), %edx ; load v[0]
movl 4(%eax), %ecx ; load v[1]
movl 8(%eax), %esi ; load v[2]
movl %edx, (%edi) ; vbptr[0] = v[0]
movl %ecx, 4(%edi) ; vbptr[1] = v[1]
movl %esi, 8(%edi) ; vbptr[2] = v[2]
movl 12(%eax), %esi ; load v[3]
movl %esi, 12(%edi) ; vbptr[3] = v[3]
addl $16, %edi ; vbptr += 4
movl $0x0, %ecx ; vertex_size - 4
movl $0x0, %esi ; tnl->vtx.vertex + 3
movl SUBST(0), %edi // load tnl->vtx.vbptr
movl (%ecx), %edx // load v[0]
movl 4(%ecx), %eax // load v[1]
movl 8(%ecx), %esi // load v[2]
movl 12(%ecx), %ecx // load v[3]
movl %edx, (%edi) // tnl->vtx.vbptr[0] = v[0]
movl %eax, 4(%edi) // tnl->vtx.vbptr[1] = v[1]
movl %esi, 8(%edi) // tnl->vtx.vbptr[2] = v[2]
movl %ecx, 12(%edi) // tnl->vtx.vbptr[3] = v[3]
addl $16, %edi // tnl->vtx.vbptr += 4
movl $SUBST(1), %ecx // vertex_size - 4
movl $SUBST(2), %esi // tnl->vtx.vertex + 3
repz
movsl %ds:(%esi), %es:(%edi)
movl %edi, (0) ; save vbptr
movl (0), %edx ; load counter
movsl %ds:(%esi), %es:(%edi)
movl %edi, SUBST(0) // save tnl->vtx.vbptr
movl SUBST(3), %edx // load counter
pop %esi
pop %edi
dec %edx ; counter--
movl %edx, (0) ; save counter
je .6 ; if (counter != 0)
ret ; return
.6: jmp *0 ; else notify();
GLOBL ( _x86_Vertex3fv_end )
dec %edx // counter--
movl %edx, SUBST(3) // save counter
je .6 // if (counter != 0)
ret // return
.8: mov $SUBST(4), %eax // else notify()
jmp *%eax // jmp $0x10101014 doesn't seem to work
GLOBL ( _x86_Vertex4fv_end )
@ -151,92 +167,151 @@ GLOBL ( _x86_Vertex3fv_end )
*/
GLOBL( _x86_Attribute1fv)
/* 'v' is already in eax */
movl (%eax), %ecx /* load v[0] */
movl %ecx, 0 /* store v[0] to current vertex */
movl 4(%esp), %ecx
movl (%ecx), %eax /* load v[0] */
movl %eax, SUBST(0) /* store v[0] to current vertex */
ret
GLOBL ( _x86_Attribute2fv_end )
GLOBL ( _x86_Attribute1fv_end )
GLOBL( _x86_Attribute2fv)
/* 'v' is already in eax */
movl (%eax), %ecx /* load v[0] */
movl 4(%eax), %eax /* load v[1] */
movl %ecx, 0 /* store v[0] to current vertex */
movl %eax, 4 /* store v[1] to current vertex */
movl 4(%esp), %ecx
movl (%ecx), %eax /* load v[0] */
movl 4(%ecx), %edx /* load v[1] */
movl %eax, SUBST(0) /* store v[0] to current vertex */
movl %edx, SUBST(1) /* store v[1] to current vertex */
ret
GLOBL ( _x86_Attribute2fv_end )
GLOBL( _x86_Attribute3fv)
/* 'v' is already in eax */
movl (%eax), %ecx /* load v[0] */
movl 4(%eax), %edx /* load v[1] */
movl 8(%eax), %eax /* load v[2] */
movl %ecx, 0 /* store v[0] to current vertex */
movl %edx, 4 /* store v[1] to current vertex */
movl %eax, 8 /* store v[2] to current vertex */
movl 4(%esp), %ecx
movl (%ecx), %eax /* load v[0] */
movl 4(%ecx), %edx /* load v[1] */
movl 8(%ecx), %ecx /* load v[2] */
movl %eax, SUBST(0) /* store v[0] to current vertex */
movl %edx, SUBST(1) /* store v[1] to current vertex */
movl %ecx, SUBST(2) /* store v[2] to current vertex */
ret
GLOBL ( _x86_Attribute3fv_end )
GLOBL( _x86_Attribute4fv)
/* 'v' is already in eax */
movl (%eax), %ecx /* load v[0] */
movl 4(%eax), %edx /* load v[1] */
movl %ecx, 0 /* store v[0] to current vertex */
movl %edx, 4 /* store v[1] to current vertex */
movl 8(%eax), %ecx /* load v[2] */
movl 12(%eax), %edx /* load v[3] */
movl %ecx, 8 /* store v[2] to current vertex */
movl %edx, 12 /* store v[3] to current vertex */
movl 4(%esp), %ecx
movl (%ecx), %eax /* load v[0] */
movl 4(%ecx), %edx /* load v[1] */
movl %eax, SUBST(0) /* store v[0] to current vertex */
movl %edx, SUBST(1) /* store v[1] to current vertex */
movl 8(%ecx), %eax /* load v[2] */
movl 12(%ecx), %edx /* load v[3] */
movl %eax, SUBST(2) /* store v[2] to current vertex */
movl %edx, SUBST(3) /* store v[3] to current vertex */
ret
GLOBL ( _x86_Attribute3fv_end )
GLOBL ( _x86_Attribute4fv_end )
;;; In the 1st level dispatch functions, switch to a different
;;; calling convention -- (const GLfloat *v) in %eax.
;;;
;;; As with regular (x86) dispatch, don't create a new stack frame -
;;; just let the 'ret' in the dispatched function return straight
;;; back to the original caller.
// Choosers:
// Must generate all of these ahead of first usage. Generate at
// compile-time?
// NOT CURRENTLY USED
GLOBL( _x86_choose_fv)
subl $12, %esp // gcc does 16 byte alignment of stack frames?
movl $SUBST(0), (%esp) // arg 0 - attrib
movl $SUBST(1), 4(%esp) // arg 1 - N
call _do_choose // new function returned in %eax
add $12, %esp // tear down stack frame
jmp *%eax // jump to new func
GLOBL ( _x86_choosefv_end )
// FIRST LEVEL FUNCTIONS -- these are plugged directly into GL dispatch.
// NOT CURRENTLY USED
// In the 1st level dispatch functions, switch to a different
// calling convention -- (const GLfloat *v) in %ecx.
//
// As with regular (x86) dispatch, don't create a new stack frame -
// just let the 'ret' in the dispatched function return straight
// back to the original caller.
;;; Vertex/Normal/Color, etc: the address of the function pointer
;;; is known at codegen time.
// Vertex/Normal/Color, etc: the address of the function pointer
// is known at codegen time.
// Unfortunately, have to play with the stack in the non-fv case:
//
GLOBL( _x86_dispatch_attrf )
leal 4(%esp), %eax
jmp *foo
subl $12, %esp // gcc does 16 byte alignment of stack frames?
leal 16(%esp), %edx // address of first float on stack
movl %edx, (%esp) // save as 'v'
call SUBST(0) // 0x0 --> tabfv[attr][n]
addl $12, %esp // tear down frame
ret // return
GLOBL( _x86_dispatch_attrf_end )
// The fv case is simpler:
//
GLOBL( _x86_dispatch_attrfv )
movl 4(%esp), %eax
jmp *foo
GLOBL( _x86_dispatch_attr1f_end )
jmp SUBST(0) // 0x0 --> tabfv[attr][n]
GLOBL( _x86_dispatch_attrfv_end )
;;; MultiTexcoord: the address of the function pointer must be
;;; calculated.
// MultiTexcoord: the address of the function pointer must be
// calculated, but can use the index argument slot to hold 'v', and
// avoid setting up a new stack frame.
// Also, will only need a maximum of four of each of these per context:
//
GLOBL( _x86_dispatch_multitexcoordf )
leal 4(%esp), %eax
jmp *foo
movl 4(%esp), %ecx
leal 8(%esp), %edx
andl $7, %ecx
movl %edx, 4(%esp)
sall $4, %ecx
jmp *SUBST(0)(%ecx) // 0x0 - tabfv[tex0][n]
GLOBL( _x86_dispatch_multitexcoordf_end )
GLOBL( _x86_dispatch_multitexcoordfv )
movl 4(%esp), %eax
jmp *foo
movl 4(%esp), %ecx
movl 8(%esp), %edx
andl $7, %ecx
movl %edx, 4(%esp)
sall $4, %ecx
jmp *SUBST(0)(%ecx) // 0x0 - tabfv[tex0][n]
GLOBL( _x86_dispatch_multitexcoordfv_end )
;;; VertexAttrib: the address of the function pointer must be
;;; calculated.
// VertexAttrib: the address of the function pointer must be
// calculated.
GLOBL( _x86_dispatch_vertexattribf )
leal 4(%esp), %eax
jmp *foo
movl $16, %ecx
movl 4(%esp), %eax
cmpl $16, %eax
cmovge %ecx, %eax
leal 8(%esp), %ecx // calculate 'v'
movl %ecx, 4(%esp) // save in 1st arg slot
sall $4, %eax
jmp *SUBST(0)(%eax) // 0x0 - tabfv[0][n]
GLOBL( _x86_dispatch_vertexattribf_end )
GLOBL( _x86_dispatch_vertexattribfv )
movl $16, %ecx
movl 4(%esp), %eax
jmp *foo
cmpl $16, %eax
cmovge %ecx, %eax
movl 8(%esp), %ecx // load 'v'
movl %ecx, 4(%esp) // save in 1st arg slot
sall $4, %eax
jmp *SUBST(0)(%eax) // 0x0 - tabfv[0][n]
GLOBL( _x86_dispatch_vertexattribfv_end )