#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
/* 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;
/* 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) {
GLfloat *tmp;
GLint lastcount = tnl->vtx.initial_counter - tnl->vtx.counter;
-
/* Run pipeline on current vertices, copy wrapped vertices
* to tnl->vtx.copied.
*/
* 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:
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];
+ }
+
}
}
+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];
+
+ assert(attr < _TNL_MAX_ATTR_CODEGEN);
- if (tnl->vtx.attrsz[attr] != sz)
+ 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;
- else
- ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
+ /* 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;
+ }
- /* Reset any active pointers for this attribute
- */
- tnl->vtx.tabfv[attr][0] = choose1;
- tnl->vtx.tabfv[attr][1] = choose2;
- tnl->vtx.tabfv[attr][2] = choose3;
- tnl->vtx.tabfv[attr][3] = choose4;
- /* Update the secondary dispatch table with the new function
+ /* Try to use codegen:
+ */
+ if (tnl->AllowCodegen)
+ tnl->vtx.tabfv[attr][sz-1] = do_codegen( ctx, attr, sz );
+ else
+ tnl->vtx.tabfv[attr][sz-1] = 0;
+
+ /* Else use generic version:
*/
- tnl->vtx.tabfv[attr][sz-1] = fallback_attr_func;
+ if (!tnl->vtx.tabfv[attr][sz-1])
+ tnl->vtx.tabfv[attr][sz-1] = generic_attr_func[attr][sz-1];
- (*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 ); \
-}
-
-#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; \
+ attrfv_func f = do_choose(ATTR, N); \
+ f( v ); \
}
-
-#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 )
{
_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 );
-
- for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
- 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 );
-}
+ GLuint i;
-static void GLAPIENTRY _tnl_VertexAttrib3fvNV( GLuint index,
- const GLfloat *v )
-{
- if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
- DISPATCH_ATTR3FV( index, v );
-}
+ 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;
-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 );
-}
+ if (i < _TNL_MAX_ATTR_CODEGEN)
+ tnl->vtx.tabfv[i][j] = choose[i][j];
+ }
-static void GLAPIENTRY _tnl_VertexAttrib4fvNV( GLuint index,
- const GLfloat *v )
-{
- if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
- DISPATCH_ATTR4FV( index, v );
+ tnl->vtx.vertex_size = 0;
+ tnl->vtx.have_materials = 0;
}
+
/* Materials:
*
* 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 )
_mesa_error( ctx, GL_INVALID_ENUM, "glMaterialfv" );
return;
}
-}
-
-#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)
+ tnl->vtx.have_materials = GL_TRUE;
+}
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
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;
}
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;
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;
_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;
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] );
+ }
}
**************************************************************************/
-
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
-
#define GLOBL( x ) \
.globl 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 )
*/
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 )
+
+
+// Choosers:
+
+// Must generate all of these ahead of first usage. Generate at
+// compile-time?
+
+// NOT CURRENTLY USED
-;;; 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.
+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.
-;;; Vertex/Normal/Color, etc: the address of the function pointer
-;;; is known at codegen time.
+
+// 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.
+
+
+// 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 )
-
\ No newline at end of file
+