diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/tnl/t_vtx_api.c | 1228 |
1 files changed, 659 insertions, 569 deletions
diff --git a/src/mesa/tnl/t_vtx_api.c b/src/mesa/tnl/t_vtx_api.c index 4076051c87c..d734b67dbd8 100644 --- a/src/mesa/tnl/t_vtx_api.c +++ b/src/mesa/tnl/t_vtx_api.c @@ -31,765 +31,821 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Keith Whitwell <[email protected]> */ #include "mtypes.h" +#include "context.h" #include "colormac.h" #include "simple_list.h" -#include "vtxfmt.h" +#include "api_arrayelt.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. - */ +#include "t_context.h" +#include "t_vtx_api.h" -/* MultiTexcoord ends up with both of these branches, unfortunately - * (it may get its own version of the macro after size-tracking is - * working). +/* 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, which can be avoided with codegen. * - * Errors (VertexAttribNV when ATTR>15) are handled at a higher level. + * 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 ATTRF( ATTR, N, A, B, C, D ) \ +#define ATTRF( ATTR, N, A, B, C, D ) \ +{ \ + GET_CURRENT_CONTEXT( ctx ); \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + \ + if ((ATTR) == 0) { \ + int i; \ + \ + if (N>0) tnl->vtx.vbptr[0].f = A; \ + if (N>1) tnl->vtx.vbptr[1].f = B; \ + if (N>2) tnl->vtx.vbptr[2].f = C; \ + if (N>3) tnl->vtx.vbptr[3].f = D; \ + \ + for (i = N; i < tnl->vtx.vertex_size; i++) \ + tnl->vtx.vbptr[i].ui = tnl->vtx.vertex[i].ui; \ + \ + tnl->vtx.vbptr += tnl->vtx.vertex_size; \ + \ + if (--tnl->vtx.counter == 0) \ + _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); \ + } \ + else { \ + union uif *dest = tnl->vtx.attrptr[ATTR]; \ + if (N>0) dest[0].f = A; \ + if (N>1) dest[1].f = B; \ + if (N>2) dest[2].f = C; \ + if (N>3) dest[3].f = D; \ + } \ +} + +#define ATTR4F( ATTR, A, B, C, D ) ATTRF( ATTR, 4, A, B, C, D ) +#define ATTR3F( ATTR, A, B, C ) ATTRF( ATTR, 3, A, B, C, 1 ) +#define ATTR2F( ATTR, A, B ) ATTRF( ATTR, 2, A, B, 0, 1 ) +#define ATTR1F( ATTR, A ) ATTRF( ATTR, 1, A, 0, 0, 1 ) + +#define ATTRS( ATTRIB ) \ +static void attrib_##ATTRIB##_1_0( GLfloat s ) \ { \ - GET_CURRENT_CONTEXT( ctx ); \ - TNLcontext *tnl = TNL_CONTEXT(ctx); \ + ATTR1F( ATTRIB, s ); \ +} \ \ - if ((ATTR) == 0) { \ - int i; \ +static void attrib_##ATTRIB##_1_1( const GLfloat *v ) \ +{ \ + ATTR1F( ATTRIB, v[0] ); \ +} \ \ - if (N>0) tnl->vbptr[0].f = A; \ - if (N>1) tnl->vbptr[1].f = B; \ - if (N>2) tnl->vbptr[2].f = C; \ - if (N>3) tnl->vbptr[3].f = D; \ +static void attrib_##ATTRIB##_2_0( GLfloat s, GLfloat t ) \ +{ \ + ATTR2F( ATTRIB, s, t ); \ +} \ \ - for (i = N; i < tnl->vertex_size; i++) \ - *tnl->vbptr[i].i = tnl->vertex[i].i; \ +static void attrib_##ATTRIB##_2_1( const GLfloat *v ) \ +{ \ + ATTR2F( ATTRIB, v[0], v[1] ); \ +} \ \ - tnl->vbptr += tnl->vertex_size; \ +static void attrib_##ATTRIB##_3_0( GLfloat s, GLfloat t, \ + GLfloat r ) \ +{ \ + ATTR3F( ATTRIB, s, t, r ); \ +} \ \ - if (--tnl->counter == 0) \ - tnl->notify(); \ - } \ - else { \ - GLfloat *dest = tnl->attrptr[ATTR]; \ - 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] ); +static void attrib_##ATTRIB##_3_1( const GLfloat *v ) \ +{ \ + ATTR3F( ATTRIB, v[0], v[1], v[2] ); \ +} \ + \ +static void attrib_##ATTRIB##_4_0( GLfloat s, GLfloat t, \ + GLfloat r, GLfloat q ) \ +{ \ + ATTR4F( ATTRIB, s, t, r, q ); \ +} \ + \ +static void attrib_##ATTRIB##_4_1( const GLfloat *v ) \ +{ \ + ATTR4F( ATTRIB, v[0], v[1], v[2], v[3] ); \ } - -/* Color +/* Generate a lot of functions. These are the actual worker + * functions, which are equivalent to those generated via codegen + * elsewhere. */ -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 ); -} +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 ) + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void _tnl_upgrade_vertex( GLcontext *ctx, + GLuint attr, + GLuint newsz ) +{ + GLuint oldsz = tnl->vtx.attrib[attr].sz; + + _tnl_flush_immediate( ctx ); + + tnl->vtx.attrib[attr].sz = newsz; + /* What else to do here? + */ -static void tnl_Color4ubv( const GLubyte *v ) -{ - ATTR4UB( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] ); + /* Replay stored vertices to translate them to new format: Use + * bitmap and ffs() to speed inner loop: + */ + for (i = 0 ; i < tnl->copied_verts.nr ; i++) { + GLfloat *data = old_data + tnl->copied_verts.offset[i]; + + for (j = 1 ; j < MAX_ATTRIB ; j++) { + if (tnl->vtx.attrib[j].sz) { + if (j == attr) { + GLfloat tmp[4]; + COPY_4FV( tmp, id ); + COPY_SZ_4V( tmp, oldsz, data ); + data += oldsz; + tnl->vtx.attrib[attr].fv( tmp ); + } + else { + GLfloat *tmp = data; + data += tnl->vtx.attrib[j].sz; + tnl->vtx.attrib[j].fv( tmp ); + } + } + } + } } -static void tnl_Color3f( GLfloat r, GLfloat g, GLfloat b ) +static void _tnl_wrap_buffers( GLcontext *ctx ) { - ATTR3F( VERT_ATTRIB_COLOR0, r, g, b ); -} + _tnl_flush_immediate( ctx ); -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 ); + /* Replay stored vertices - don't really need to do this, memcpy + * would be fine. + */ + for (i = 0 ; i < tnl->copied_verts.nr ; i++) { + for (j = 1 ; j < MAX_ATTRIB ; j++) { + GLfloat *tmp = data; + data += tnl->vtx.attrib[j].sz; + tnl->vtx.attrib[j].fv( tmp ); + } + } } -static void tnl_Color4fv( const GLfloat *v ) -{ - ATTR4F( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] ); -} -/* Secondary Color +/* The functions defined below (CHOOSERS) are the initial state for + * dispatch entries for all entrypoints except those requiring + * double-dispatch (multitexcoord, material, vertexattrib). + * + * These may provoke a vertex-upgrade where the existing vertex buffer + * is flushed and a new element is added to the active vertex layout. + * This can happen between begin/end pairs. */ -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 +/* An active attribute has changed size. */ -static void tnl_FogCoordfEXT( GLfloat f ) +static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ) { - ATTR1F( VERT_ATTRIB_FOG, f ); -} + TNLcontext *tnl = TNL_CONTEXT(ctx); -static void tnl_FogCoordfvEXT( const GLfloat *v ) -{ - ATTR1F( VERT_ATTRIB_FOG, v[0] ); + if (tnl->vtx.attrib_sz[attr] < sz) { + /* New size is larger. Need to flush existing vertices and get + * an enlarged vertex format. + */ + _tnl_upgrade_vertex( tnl, attr, sz ); + } + else { + static float id[4] = { 0, 0, 0, 1 }; + int i; + + /* New size is smaller - just need to fill in some zeros. + */ + for (i = sz ; i < tnl->vtx.attrib_sz[attr] ; i++) + tnl->vtx.attrptr[attr][i].f = id[i]; + } + + /* Reset the dispatch table - aliasing entrypoints are invalidated. + */ + _tnl_reset_attr_dispatch_tab( ctx ); } +static int dispatch_offset[TNL_ATTRIB_MAX][4][2]; -/* 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] ); -} - +static void *lookup_or_generate( GLuint attr, GLuint sz, GLuint v, + void *fallback_attr_func ) +{ + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + void *ptr = 0; + struct dynfn *dfn; + int key; -/* TexCoord - */ -static void tnl_TexCoord1f( GLfloat s ) -{ - ATTR1F( VERT_ATTRIB_TEX0, s ); -} + /* This will remove any installed handlers for attr with different + * sz, will flush, copy and expand the copied vertices if sz won't + * fit in the current vertex, or will clean the current vertex if + * it already has this attribute in a larger size. + */ + if (tnl->vtx.attrib_sz[attr] != sz) + _tnl_fixup_vertex( ctx, attr, sz ); -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 ); -} + if (attr == 0) + key = tnl->vtx.vertex_size; + else + key = (GLuint)tnl->vtx.attrptr[attr]; -static void tnl_TexCoord2fv( const GLfloat *v ) -{ - ATTR2F( VERT_ATTRIB_TEX0, v[0], v[1] ); -} + for (dfn = tnl->vtx.generated[sz-1][v][isvertex]; dfn; dfn = dfn->next) { + if (dfn->key == key) { + ptr = dfn->code; + break; + } + } -static void tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r ) -{ - ATTR3F( VERT_ATTRIB_TEX0, s, t, r ); -} + if (ptr == 0) { + dfn = tnl->vtx.codegen[sz-1][v][isvertex]( ctx, key ); + if (dfn) { + ptr = dfn->code; + dfn->next = tnl->vtx.generated[sz-1][v][isvertex]; + tnl->vtx.generated[sz-1][v][isvertex] = dfn; + } + } + + if (ptr == 0) + ptr = fallback_attr_func; -static void tnl_TexCoord3fv( const GLfloat *v ) -{ - ATTR3F( VERT_ATTRIB_TEX0, v[0], v[1], v[2] ); -} + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; -static void tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q ) -{ - ATTR4F( VERT_ATTRIB_TEX0, s, t, r, q ); -} + /* Need to set all the aliases to this function, too + */ + if (dispatch_offset[attr][sz-1][v]) + ((void **)tnl->Exec)[dispatch_offset[attr][sz-1][v]] = ptr; -static void tnl_TexCoord4fv( const GLfloat *v ) -{ - ATTR4F( VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3] ); + return ptr; } -/* Miscellaneous: +/* These functions choose one of the ATTR's generated above (or from + * codegen). Like the ATTR functions, they live in the GL dispatch + * table and in the second-level dispatch table for MultiTexCoord, + * AttribNV, etc. * - * These don't alias NV attributes, but still need similar treatment. - * Basically these are attributes with numbers greater than 16. + * Need ATTR1 for use in constructing name of 'attrib_x_y_z' function. */ -static void tnl_EdgeFlag( GLboolean flag ) -{ - GLfloat f = flag ? 1 : 0; - ATTR1F( VERT_ATTRIB_EDGEFLAG, f); -} - -static void tnl_EdgeFlagv( const GLboolean *flag ) -{ - GLfloat f = flag[0] ? 1 : 0; - ATTR1F( VERT_ATTRIB_EDGEFLAG, f); +#define CHOOSE( ATTR1, ATTR2, SZ, V, FNTYPE, ARGS1, ARGS2 ) \ +static void choose_##ATTR2##_##SZ##_##V ARGS1 \ +{ \ + void *ptr = lookup_or_generate(ATTR1, SZ, V, \ + (void *)attrib_##ATTR1##_##SZ##_##V ); \ + \ + assert(ATTR1 == ATTR2); \ + ((FNTYPE) ptr) ARGS2; \ } -static void tnl_Indexi( GLint idx ) -{ - ATTR1F( VERT_ATTRIB_INDEX, idx ); -} +#define afv (const GLfloat *v) +#define a1f (GLfloat a) +#define a2f (GLfloat a, GLfloat b) +#define a3f (GLfloat a, GLfloat b, GLfloat c) +#define a4f (GLfloat a, GLfloat b, GLfloat c, GLfloat d) -static void tnl_Indexiv( const GLint *idx ) -{ - ATTR1F( VERT_ATTRIB_INDEX, idx ); -} - -/* Use dispatch switching to build 'ranges' of eval vertices for each - * type, avoiding need for flags. (Make - * evalcoords/evalpoints/vertices/attr0 mutually exclusive) +/* Not that many entrypoints when it all boils down: */ -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] ); -} - +CHOOSE( 0, VERT_ATTRIB_POS, 2, 1, pfv, afv, (v) ) +CHOOSE( 0, VERT_ATTRIB_POS, 2, 0, p2f, a2f, (a,b) ) +CHOOSE( 0, VERT_ATTRIB_POS, 3, 1, pfv, afv, (v) ) +CHOOSE( 0, VERT_ATTRIB_POS, 3, 0, p3f, a3f, (a,b,c) ) +CHOOSE( 0, VERT_ATTRIB_POS, 4, 1, pfv, afv, (v) ) +CHOOSE( 0, VERT_ATTRIB_POS, 4, 0, p4f, a4f, (a,b,c,d) ) +CHOOSE( 2, VERT_ATTRIB_NORMAL, 3, 1, pfv, afv, (v) ) +CHOOSE( 2, VERT_ATTRIB_NORMAL, 3, 0, p3f, a3f, (a,b,c) ) +CHOOSE( 3, VERT_ATTRIB_COLOR0, 3, 1, pfv, afv, (v) ) +CHOOSE( 3, VERT_ATTRIB_COLOR0, 3, 0, p3f, a3f, (a,b,c) ) +CHOOSE( 3, VERT_ATTRIB_COLOR0, 4, 1, pfv, afv, (v) ) +CHOOSE( 3, VERT_ATTRIB_COLOR0, 4, 0, p4f, a4f, (a,b,c,d) ) +CHOOSE( 4, VERT_ATTRIB_COLOR1, 3, 1, pfv, afv, (v) ) +CHOOSE( 4, VERT_ATTRIB_COLOR1, 3, 0, p3f, a3f, (a,b,c) ) +CHOOSE( 5, VERT_ATTRIB_FOG, 1, 1, pfv, afv, (v) ) +CHOOSE( 5, VERT_ATTRIB_FOG, 1, 0, p1f, a1f, (a) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 1, 1, pfv, afv, (v) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 1, 0, p1f, a1f, (a) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 2, 1, pfv, afv, (v) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 2, 0, p2f, a2f, (a,b) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 3, 1, pfv, afv, (v) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 3, 0, p3f, a3f, (a,b,c) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 4, 1, pfv, afv, (v) ) +CHOOSE( 8, VERT_ATTRIB_TEX0, 4, 0, p4f, a4f, (a,b,c,d) ) + + +/* Gack. Need to do this without going through the + * GET_CURRENT_CONTEXT hoohah. Could codegen this, I suppose... + */ +#define DISPATCH_ATTRFV( ATTR, COUNT, P ) \ +do { \ + GET_CURRENT_CONTEXT( ctx ); \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + tnl->vtx.tabfv[COUNT-1][ATTR]( 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 ) -/* Second level dispatch table for MultiTexCoord, Material and - * VertexAttribNV. - * - * Need this because we want to track things like vertex attribute - * sizes, presence/otherwise of attribs in recorded vertices, etc, by - * manipulating the state of dispatch tables. Need therefore a - * dispatch slot for each value of 'index' or 'unit' in VertexAttribNV - * and MultiTexCoordARB. Also need a mechnism for keeping this data - * consistent with what's coming in via the Vertex/Normal/etc api - * above (where aliasing exists with the traditional entrypoints). - * Note that MultiTexCoordARB aliases with TexCoord when unit==0. - * - * Need presence tracking for material components, too, but not size - * tracking or help with aliasing. Could move material to seperate - * dispatch without the "*4" below, or even do the checks every time. +#define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) ) +#ifdef USE_X86_ASM +/* Naughty cheat: */ -struct attr_dispatch_tab { - void (*tab[32*4])( void ); - void (*swapped[32*4])( void ); - int swapcount; - int installed_sizes[32]; -}; - -#define DISPATCH_ATTR1F( ATTR, N, ) - tnl->vb.attr_dispatch - -/* Result at the back end after second dispatch -- could further - * specialize for attr zero -- maybe just in the codegen version. +#define DISPATCH_ATTR2F( ATTR, S,T ) DISPATCH_ATTRFV( ATTR, 2, &(S) ) +#define DISPATCH_ATTR3F( ATTR, S,T,R ) DISPATCH_ATTRFV( ATTR, 3, &(S) ) +#define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) DISPATCH_ATTRFV( ATTR, 4, &(S) ) +#else +/* Safe: */ -static void tnl_Attr1f( GLint attr, GLfloat s ) -{ - ATTR1F( attr, s ); -} - -static void tnl_Attr1fv( GLint attr, const GLfloat *v ) -{ - ATTR1F( attr, v[0] ); -} +#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) +#endif -static void tnl_Attr2f( GLint attr, GLfloat s, GLfloat t ) -{ - ATTR2F( attr, s, t ); -} -static void tnl_Attr2fv( GLint attr, const GLfloat *v ) -{ - ATTR2F( attr, v[0], v[1] ); -} -static void tnl_Attr3f( GLint attr, GLfloat s, GLfloat t, GLfloat r ) +static void enum_error( void ) { - ATTR3F( attr, s, t, r ); + GET_CURRENT_CONTEXT( ctx ); + _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); } -static void tnl_Attr3fv( GLint attr, const GLfloat *v ) +static void op_error( void ) { - ATTR3F( attr, v[0], v[1], v[2] ); + GET_CURRENT_CONTEXT( ctx ); + _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ ); } -static void tnl_Attr4f( GLint attr, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) -{ - ATTR4F( attr, s, t, r, q ); -} -static void tnl_Attr4fv( GLint attr, const GLfloat *v ) -{ - ATTR4F( attr, v[0], v[1], v[2], v[3] ); -} - - -/* MultiTexcoord: Send through second level dispatch. +/* First level for MultiTexcoord: Send through second level dispatch. + * These are permanently installed in the toplevel dispatch. + * + * Assembly can optimize the generation of arrays by using &s instead + * of building 'v'. */ -static void tnl_MultiTexCoord1fARB( GLenum target, GLfloat s ) +static void _tnl_MultiTexCoord1f( GLenum target, GLfloat s ) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR1F( attr, s ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR1FV( attr, &s ); } -static void tnl_MultiTexCoord1fvARB( GLenum target, const GLfloat *v ) +static void _tnl_MultiTexCoord1fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR1F( attr, v[0] ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR1FV( attr, v ); } -static void tnl_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t ) +static void _tnl_MultiTexCoord2f( GLenum target, GLfloat s, GLfloat t ) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR2F( attr, s, t ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR2F( attr, s, t ); } -static void tnl_MultiTexCoord2fvARB( GLenum target, const GLfloat *v ) +static void _tnl_MultiTexCoord2fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR2F( attr, v[0], v[1] ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR2FV( attr, v ); } -static void tnl_MultiTexCoord3fARB( GLenum target, GLfloat s, GLfloat t, +static void _tnl_MultiTexCoord3f( GLenum target, GLfloat s, GLfloat t, GLfloat r) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR3F( attr, s, t, r ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR3F( attr, s, t, r ); } -static void tnl_MultiTexCoord3fvARB( GLenum target, const GLfloat *v ) +static void _tnl_MultiTexCoord3fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR3F( attr, v[0], v[1], v[2] ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR3FV( attr, v ); } -static void tnl_MultiTexCoord4fARB( GLenum target, GLfloat s, GLfloat t, +static void _tnl_MultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR4F( attr, s, t, r, q ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR4F( attr, s, t, r, q ); } -static void tnl_MultiTexCoord4fvARB( GLenum target, const GLfloat *v ) +static void _tnl_MultiTexCoord4fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; - if (attr < MAX_VERT_ATTRS) - DISPATCH_ATTR4F( attr, v[0], v[1], v[2], v[3] ); + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + DISPATCH_ATTR4FV( attr, v ); } -/* NV_vertex_program: +/* First level for NV_vertex_program: * * Check for errors & reroute through second dispatch layer to get * size tracking per-attribute. */ -static void tnl_VertexAttrib1fNV( GLuint index, GLfloat s ) +static void _tnl_VertexAttrib1fNV( GLuint index, GLfloat s ) { - if (index < MAX_VERT_ATTRS) + if (index < TNL_ATTRIB_MAX) DISPATCH_ATTR1F( index, s ); else - DISPATCH_ERROR; + enum_error(); } -static void tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) +static void _tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) { - if (index < MAX_VERT_ATTRS) - DISPATCH_ATTR1F( index, v[0] ); + if (index < TNL_ATTRIB_MAX) + DISPATCH_ATTR1FV( index, v ); else - DISPATCH_ERROR; + enum_error(); } -static void tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t ) +static void _tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t ) { - if (index < MAX_VERT_ATTRS) + if (index < TNL_ATTRIB_MAX) DISPATCH_ATTR2F( index, s, t ); else - DISPATCH_ERROR; + enum_error(); } -static void tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) +static void _tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) { - if (index < MAX_VERT_ATTRS) - DISPATCH_ATTR2F( index, v[0], v[1] ); + if (index < TNL_ATTRIB_MAX) + DISPATCH_ATTR2FV( index, v ); else - DISPATCH_ERROR; + enum_error(); } -static void tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t, +static void _tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t, GLfloat r ) { - if (index < MAX_VERT_ATTRS) + if (index < TNL_ATTRIB_MAX) DISPATCH_ATTR3F( index, s, t, r ); else - DISPATCH_ERROR; + enum_error(); } -static void tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) +static void _tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) { - if (index < MAX_VERT_ATTRS) - DISPATCH_ATTR3F( index, v[0], v[1], v[2] ); + if (index < TNL_ATTRIB_MAX) + DISPATCH_ATTR3FV( index, v ); else - DISPATCH_ERROR; + enum_error(); } -static void tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t, +static void _tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) { - if (index < MAX_VERT_ATTRS) + if (index < TNL_ATTRIB_MAX) DISPATCH_ATTR4F( index, s, t, r, q ); else - DISPATCH_ERROR; + enum_error(); } -static void tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) +static void _tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) { - if (index < MAX_VERT_ATTRS) - DISPATCH_ATTR4F( index, v[0], v[1], v[2], v[3] ); + if (index < TNL_ATTRIB_MAX) + DISPATCH_ATTR4FV( index, v ); else - DISPATCH_ERROR; + enum_error(); } - - - - - /* Materials: * * These are treated as per-vertex attributes, at indices above where * the NV_vertex_program leaves off. There are a lot of good things * about treating materials this way. * - * *** Need a dispatch step (like VertexAttribute GLint attr, and MultiTexCoord) - * *** to expand vertex size, etc. Use the same second level dispatch - * *** (keyed by attr number) as above. + * However: I don't want to double the number of generated functions + * just to cope with this, so I unroll the 'C' varients of CHOOSE and + * ATTRF into this function, and dispense with codegen and + * second-level dispatch. */ -#define MAT( ATTR, face, params ) \ -do { \ - if (face != GL_BACK) \ - DISPATCH_ATTRF( ATTR, N, params ); \ - if (face != GL_FRONT) \ - DISPATCH_ATTRF( ATTR+7, N, params ); \ +#define MAT_ATTR( A, N, params ) \ +do { \ + if (tnl->vtx.attrib_sz[A] != N) { \ + tnl_fixup_vertex( ctx, A, N ); \ + } \ + \ + { \ + union uif *dest = tnl->vtx.attrptr[A]; \ + if (N>0) dest[0].f = params[0]; \ + if (N>1) dest[1].f = params[1]; \ + if (N>2) dest[2].f = params[2]; \ + if (N>3) dest[3].f = 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 */ \ } while (0) -/* NOTE: Have to remove/dealwith colormaterial crossovers, probably - * later on - in the meantime just store everything. +/* NOTE: Have to remove/deal-with colormaterial crossovers, probably + * later on - in the meantime just store everything. */ static void _tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params ) { + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + switch (pname) { case GL_EMISSION: - MAT( VERT_ATTRIB_FRONT_EMMISSION, 4, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); break; case GL_AMBIENT: - MAT( VERT_ATTRIB_FRONT_AMBIENT, 4, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); break; case GL_DIFFUSE: - MAT( VERT_ATTRIB_FRONT_DIFFUSE, 4, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); break; case GL_SPECULAR: - MAT( VERT_ATTRIB_FRONT_SPECULAR, 4, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); break; case GL_SHININESS: - MAT( VERT_ATTRIB_FRONT_SHININESS, 1, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); break; case GL_COLOR_INDEXES: - MAT( VERT_ATTRIB_FRONT_EMMISSION, 3, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); break; case GL_AMBIENT_AND_DIFFUSE: - MAT( VERT_ATTRIB_FRONT_AMBIENT, 4, face, params ); - MAT( VERT_ATTRIB_FRONT_DIFFUSE, 4, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); break; default: - _mesa_error( ctx, GL_INVALID_ENUM, where ); + _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); return; } } +#define IDX_ATTR( A, IDX ) \ +do { \ + GET_CURRENT_CONTEXT( ctx ); \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + \ + if (tnl->vtx.attrib_sz[A] != 1) { \ + tnl_fixup_vertex( ctx, A, 1 ); \ + } \ + \ + { \ + union uif *dest = tnl->vtx.attrptr[A]; \ + dest[0].ui = IDX; \ + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ + } \ +} while (0) -/* Codegen support - */ -static struct dynfn *lookup( struct dynfn *l, int key ) +static void _tnl_EdgeFlag( GLboolean f ) { - struct dynfn *f; + IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f ); +} - foreach( f, l ) { - if (f->key == key) - return f; - } +static void _tnl_EdgeFlagv( const GLboolean *f ) +{ + IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f[0] ); +} - return 0; +static void _tnl_Indexi( GLint i ) +{ + IDX_ATTR( VERT_ATTRIB_INDEX, i ); } -/* Vertex descriptor +static void _tnl_Indexiv( const GLint *i ) +{ + IDX_ATTR( VERT_ATTRIB_INDEX, i[0] ); +} + + + +/* EvalCoord needs special treatment as ususal: */ -struct _tnl_vertex_descriptor { - GLuint attr_bits[4]; -}; +static void evalcoord( GLfloat a, GLfloat b, GLuint type ) +{ +#if 0 + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* Initialize the list of eval fixups: + */ + if (!tnl->evalptr) { + init_eval_ptr( ctx ); + } + /* Note that this vertex will need to be fixed up: + */ + tnl->evalptr[0].vert = tnl->initial_counter - tnl->counter; + tnl->evalptr[0].type = type; + + /* Now emit the vertex with eval data in obj coordinates: + */ + ATTRF( 0, 2, a, b, 0, 1 ); +#endif +} + + +static void _tnl_EvalCoord1f( GLfloat u ) +{ + evalcoord( u, 0, TNL_EVAL_COORD1 ); +} + +static void _tnl_EvalCoord1fv( const GLfloat *v ) +{ + evalcoord( v[0], 0, TNL_EVAL_COORD1 ); +} + +static void _tnl_EvalCoord2f( GLfloat u, GLfloat v ) +{ + evalcoord( u, v, TNL_EVAL_COORD2 ); +} + +static void _tnl_EvalCoord2fv( const GLfloat *v ) +{ + evalcoord( v[0], v[1], TNL_EVAL_COORD2 ); +} + +static void _tnl_EvalPoint1( GLint i ) +{ + evalcoord( (GLfloat)i, 0, TNL_EVAL_POINT1 ); +} + +static void _tnl_EvalPoint2( GLint i, GLint j ) +{ + evalcoord( (GLfloat)i, (GLfloat)j, TNL_EVAL_POINT2 ); +} -/* Can't use the loopback template for this: +/* Don't do a lot of processing here - errors are raised when this + * list is scanned later on (perhaps in display list playback) to + * build tnl_prim structs. */ -#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) \ - _mesa_debug(NULL, "%s -- cached codegen\n", __FUNCTION__ ); \ - \ - if (dfn) \ - tnl->context->Exec->FN = (FNTYPE)(dfn->code); \ - else { \ - if (MESA_VERBOSE & DEBUG_CODEGEN) \ - _mesa_debug(NULL, "%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 = dd_MultiTexCoord1fARB; - vfmt->MultiTexCoord1fvARB = dd_MultiTexCoord1fvARB; - vfmt->MultiTexCoord2fARB = dd_MultiTexCoord2fARB; - vfmt->MultiTexCoord2fvARB = dd_MultiTexCoord2fvARB; - vfmt->MultiTexCoord3fARB = dd_MultiTexCoord3fARB; - vfmt->MultiTexCoord3fvARB = dd_MultiTexCoord3fvARB; - vfmt->MultiTexCoord4fARB = dd_MultiTexCoord4fARB; - vfmt->MultiTexCoord4fvARB = dd_MultiTexCoord4fvARB; - 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->TexCoord3f = choose_TexCoord3f; - vfmt->TexCoord3fv = choose_TexCoord3fv; - vfmt->TexCoord4f = choose_TexCoord4f; - vfmt->TexCoord4fv = choose_TexCoord4fv; - vfmt->Vertex2f = choose_Vertex2f; - vfmt->Vertex2fv = choose_Vertex2fv; - vfmt->Vertex3f = choose_Vertex3f; - vfmt->Vertex3fv = choose_Vertex3fv; - 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->Materialfv = dd_Materialfv; -} - - -static struct dynfn *codegen_noop( struct _vb *vb, int key ) -{ - (void) vb; (void) key; - return 0; +static void _tnl_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + int i; + + i = tnl->vtx.be_count++; + tnl->vtx.be[i].type = TNL_BEGIN; + tnl->vtx.be[i].idx = tnl->vtx.initial_counter - tnl->vtx.counter; + tnl->vtx.be[i].mode = mode; + + if (tnl->vtx.be_count == TNL_BE_MAX) + _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); } -void _tnl_InitCodegen( struct dfn_generators *gen ) +static void _tnl_End( void ) { - /* Generate an attribute or vertex command. - */ - 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; + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + int i; + + i = tnl->vtx.be_count++; + tnl->vtx.be[i].type = TNL_END; + tnl->vtx.be[i].idx = tnl->vtx.initial_counter - tnl->vtx.counter; + tnl->vtx.be[i].mode = 0; + + if (tnl->vtx.be_count == TNL_BE_MAX) + _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); +} + + + + + + + +static void _tnl_InitDispatch( struct _glapi_table *tab ) +{ + GLint i; - /* Index is never zero for these... + /* Most operations boil down to error/transition behaviour. + * However if we transition eagerly, all that's needed is a single + * 'error' operation. This will do for now, but requires that the + * old 'flush' stuff lives on in the state functions, and is + * wasteful if swapping is expensive (threads?). */ - gen->Attr3ub = codegen_noop; - gen->Attr3ubv = codegen_noop; - gen->Attr4ub = codegen_noop; - gen->Attr4ubv = codegen_noop; + for (i = 0 ; i < sizeof(tab)/sizeof(void*) ; i++) + ((void **)tab)[i] = (void *)op_error; + + tab->Begin = _tnl_Begin; + tab->End = _tnl_End; + tab->Color3f = choose_VERT_ATTRIB_COLOR0_3_0; + tab->Color3fv = choose_VERT_ATTRIB_COLOR0_3_1; + tab->Color4f = choose_VERT_ATTRIB_COLOR0_4_0; + tab->Color4fv = choose_VERT_ATTRIB_COLOR0_4_1; + tab->SecondaryColor3fEXT = choose_VERT_ATTRIB_COLOR1_3_0; + tab->SecondaryColor3fvEXT = choose_VERT_ATTRIB_COLOR1_3_1; + tab->MultiTexCoord1fARB = _tnl_MultiTexCoord1f; + tab->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fv; + tab->MultiTexCoord2fARB = _tnl_MultiTexCoord2f; + tab->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fv; + tab->MultiTexCoord3fARB = _tnl_MultiTexCoord3f; + tab->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fv; + tab->MultiTexCoord4fARB = _tnl_MultiTexCoord4f; + tab->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fv; + tab->Normal3f = choose_VERT_ATTRIB_NORMAL_3_0; + tab->Normal3fv = choose_VERT_ATTRIB_NORMAL_3_1; + tab->TexCoord1f = choose_VERT_ATTRIB_TEX0_1_0; + tab->TexCoord1fv = choose_VERT_ATTRIB_TEX0_1_1; + tab->TexCoord2f = choose_VERT_ATTRIB_TEX0_2_0; + tab->TexCoord2fv = choose_VERT_ATTRIB_TEX0_2_1; + tab->TexCoord3f = choose_VERT_ATTRIB_TEX0_3_0; + tab->TexCoord3fv = choose_VERT_ATTRIB_TEX0_3_1; + tab->TexCoord4f = choose_VERT_ATTRIB_TEX0_4_0; + tab->TexCoord4fv = choose_VERT_ATTRIB_TEX0_4_1; + tab->Vertex2f = choose_VERT_ATTRIB_POS_2_0; + tab->Vertex2fv = choose_VERT_ATTRIB_POS_2_1; + tab->Vertex3f = choose_VERT_ATTRIB_POS_3_0; + tab->Vertex3fv = choose_VERT_ATTRIB_POS_3_1; + tab->Vertex4f = choose_VERT_ATTRIB_POS_4_0; + tab->Vertex4fv = choose_VERT_ATTRIB_POS_4_1; + tab->FogCoordfEXT = choose_VERT_ATTRIB_FOG_1_0; + tab->FogCoordfvEXT = choose_VERT_ATTRIB_FOG_1_1; + tab->EdgeFlag = _tnl_EdgeFlag; + tab->EdgeFlagv = _tnl_EdgeFlagv; + tab->Indexi = _tnl_Indexi; + tab->Indexiv = _tnl_Indexiv; + tab->EvalCoord1f = _tnl_EvalCoord1f; + tab->EvalCoord1fv = _tnl_EvalCoord1fv; + tab->EvalCoord2f = _tnl_EvalCoord2f; + tab->EvalCoord2fv = _tnl_EvalCoord2fv; + tab->Materialfv = _tnl_Materialfv; + tab->ArrayElement = _ae_loopback_array_elt; /* generic helper */ +} + + + +static struct dynfn *codegen_noop( GLcontext *ctx, int key ) +{ + (void) ctx; (void) key; + return 0; +} - /* As above, but deal with the extra (redundant by now) index - * argument to the generated function. +static void _tnl_InitCodegen( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + int sz, v, z; + + /* attr[n][v] + * vertex[n][v] + * + * Generated functions parameterized by: + * nr 1..4 + * v y/n + * vertex y/n + * + * Vertex functions also parameterized by: + * vertex_size + * + * Attr functions also parameterized by: + * pointer (destination to receive data) */ - 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; - + for (sz = 1 ; sz < 5 ; sz++) { + for (v = 0 ; v < 2 ; v++) { + for (z = 0 ; z < 2 ; z++) { + tnl->vtx.codegen[sz-1][v][z] = codegen_noop; + tnl->vtx.generated[sz-1][v][z] = 0; + } + } + } +#if 0 if (!getenv("MESA_NO_CODEGEN")) { #if defined(USE_X86_ASM) _tnl_InitX86Codegen( gen ); @@ -805,4 +861,38 @@ void _tnl_InitCodegen( struct dfn_generators *gen ) #if defined(USE_SPARC_ASM) #endif } +#endif +} + + + + +void _tnl_vtx_init( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + _tnl_InitDispatch( tnl->Exec ); + _tnl_InitCodegen( ctx ); } + + + +void _tnl_vtx_destroy( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + int sz, v, z; + struct dynfn *dfn, *next; + + for (sz = 1 ; sz <= 4 ; sz++) { + for (v = 0 ; v <= 1 ; v++) { + for (z = 0 ; z <= 1 ; z++) { + dfn = tnl->vtx.generated[sz-1][v][z]; + while (dfn) { + next = dfn->next; + FREE(dfn); + dfn = next; + } + } + } + } +} + |