diff options
author | Keith Whitwell <[email protected]> | 2003-11-24 15:23:18 +0000 |
---|---|---|
committer | Keith Whitwell <[email protected]> | 2003-11-24 15:23:18 +0000 |
commit | ae0eaf93e092ac8e8b1c98f3e986de96940663fa (patch) | |
tree | 56aae7c4b985f657384df5e088227c4dd08130fb /src/mesa/tnl/t_vtx_api.c | |
parent | 57c9814b9e87924696df4c741861c29d4236d1eb (diff) |
Merge vtx-0-2-branch
Diffstat (limited to 'src/mesa/tnl/t_vtx_api.c')
-rw-r--r-- | src/mesa/tnl/t_vtx_api.c | 1319 |
1 files changed, 793 insertions, 526 deletions
diff --git a/src/mesa/tnl/t_vtx_api.c b/src/mesa/tnl/t_vtx_api.c index d734b67dbd8..21ec1c9a7b2 100644 --- a/src/mesa/tnl/t_vtx_api.c +++ b/src/mesa/tnl/t_vtx_api.c @@ -30,19 +30,303 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Keith Whitwell <[email protected]> */ -#include "mtypes.h" + #include "context.h" -#include "colormac.h" -#include "simple_list.h" +#include "macros.h" +#include "vtxfmt.h" +#include "dlist.h" +#include "state.h" +#include "light.h" #include "api_arrayelt.h" - -#include "t_context.h" +#include "api_noop.h" #include "t_vtx_api.h" +static void init_attrfv( TNLcontext *tnl ); + + +/* Close off the last primitive, execute the buffer, restart the + * primitive. + */ +static void _tnl_wrap_buffers( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + GLint i = tnl->vtx.prim_count - 1; + assert(i >= 0); + tnl->vtx.prim[i].count = ((tnl->vtx.initial_counter - tnl->vtx.counter) - + tnl->vtx.prim[i].start); + } + + /* Execute the buffer and save copied vertices. + */ + _tnl_flush_vtx( ctx ); + + /* Emit a glBegin to start the new list. + */ + assert(tnl->vtx.prim_count == 0); + + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + tnl->vtx.prim[0].mode = ctx->Driver.CurrentExecPrimitive; + tnl->vtx.prim[0].start = 0; + tnl->vtx.prim[0].count = 0; + tnl->vtx.prim_count++; + } +} + + +static void _tnl_wrap_filled_vertex( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLfloat *data = tnl->vtx.copied.buffer; + int i; + + /* Run pipeline on current vertices, copy wrapped vertices + * to tnl->copied. + */ + _tnl_wrap_buffers( ctx ); + + /* Copy stored stored vertices to start of new list. + */ + assert(tnl->vtx.counter > tnl->vtx.copied.nr); + + for (i = 0 ; i < tnl->vtx.copied.nr ; i++) { + memcpy( tnl->vtx.vbptr, data, tnl->vtx.vertex_size * sizeof(GLfloat)); + tnl->vtx.vbptr += tnl->vtx.vertex_size; + data += tnl->vtx.vertex_size; + tnl->vtx.counter--; + } + + tnl->vtx.copied.nr = 0; +} + +static void _tnl_copy_to_current( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint i; + + for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) + if (tnl->vtx.attrsz[i]) { + ASSIGN_4V( tnl->vtx.current[i], 0, 0, 0, 1 ); + COPY_SZ_4V(tnl->vtx.current[i], + tnl->vtx.attrsz[i], + tnl->vtx.attrptr[i]); + } + + /* Edgeflag requires special treatment: + */ + if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) + ctx->Current.EdgeFlag = + (tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0); + + + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled) { + _mesa_update_color_material(ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); + } + + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; +} + + +static void _tnl_copy_from_current( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLint i; + + for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) + switch (tnl->vtx.attrsz[i]) { + case 4: tnl->vtx.attrptr[i][3] = tnl->vtx.current[i][3]; + case 3: tnl->vtx.attrptr[i][2] = tnl->vtx.current[i][2]; + case 2: tnl->vtx.attrptr[i][1] = tnl->vtx.current[i][1]; + case 1: tnl->vtx.attrptr[i][0] = tnl->vtx.current[i][0]; + break; + } + + /* Edgeflag requires special treatment: + */ + if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) + tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] = + (GLfloat)ctx->Current.EdgeFlag; + + + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; +} + + + + + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void _tnl_wrap_upgrade_vertex( GLcontext *ctx, + GLuint attr, + GLuint newsz ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldsz; + GLint i; + GLfloat *tmp; + GLint lastcount = tnl->vtx.initial_counter - tnl->vtx.counter; + + + /* Run pipeline on current vertices, copy wrapped vertices + * to tnl->vtx.copied. + */ + _tnl_wrap_buffers( ctx ); + + /* Do a COPY_TO_CURRENT to ensure back-copying works for the case + * when the attribute already exists in the vertex and is having + * its size increased. + */ + _tnl_copy_to_current( ctx ); + + + /* Heuristic: Attempt to isolate attributes received outside + * begin/end so that they don't bloat the vertices. + */ +#if 1 + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && + tnl->vtx.attrsz[attr] == 0 + && lastcount > 8 + ) { + init_attrfv( tnl ); + } +#endif + + + /* Fix up sizes: + */ + oldsz = tnl->vtx.attrsz[attr]; + tnl->vtx.attrsz[attr] = newsz; + + tnl->vtx.vertex_size += newsz - oldsz; + tnl->vtx.counter = MIN2( VERT_BUFFER_SIZE / tnl->vtx.vertex_size, + ctx->Const.MaxArrayLockSize ); + tnl->vtx.initial_counter = tnl->vtx.counter; + tnl->vtx.vbptr = tnl->vtx.buffer; + + + /* Recalculate all the attrptr[] values + */ + for (i = 0, tmp = tnl->vtx.vertex ; i < _TNL_ATTRIB_MAX ; i++) { + if (tnl->vtx.attrsz[i]) { + tnl->vtx.attrptr[i] = tmp; + tmp += tnl->vtx.attrsz[i]; + } + else + tnl->vtx.attrptr[i] = 0; /* will not be dereferenced */ + } + + /* Copy from current to repopulate the vertex with correct values. + */ + _tnl_copy_from_current( ctx ); + + /* Replay stored vertices to translate them + * to new format here. + * + * -- No need to replay - just copy piecewise + */ + if (tnl->vtx.copied.nr) + { + GLfloat *data = tnl->vtx.copied.buffer; + GLfloat *dest = tnl->vtx.buffer; + GLuint j; + + for (i = 0 ; i < tnl->vtx.copied.nr ; i++) { + for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) { + if (tnl->vtx.attrsz[j]) { + if (j == attr) { + COPY_SZ_4V( dest, newsz, tnl->vtx.current[j] ); + COPY_SZ_4V( dest, oldsz, data ); + data += oldsz; + dest += newsz; + } + else { + GLuint sz = tnl->vtx.attrsz[j]; + COPY_SZ_4V( dest, sz, data ); + dest += sz; + data += sz; + } + } + } + } + + tnl->vtx.vbptr = dest; + tnl->vtx.counter -= tnl->vtx.copied.nr; + tnl->vtx.copied.nr = 0; + } +} + + +static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + static float id[4] = { 0, 0, 0, 1 }; + int i; + + if (tnl->vtx.attrsz[attr] < sz) { + /* New size is larger. Need to flush existing vertices and get + * an enlarged vertex format. + */ + _tnl_wrap_upgrade_vertex( ctx, attr, sz ); + } + else if (tnl->vtx.attrsz[attr] > sz) { + /* New size is smaller - just need to fill in some + * zeros. Don't need to flush or wrap. + */ + for (i = sz ; i <= tnl->vtx.attrsz[attr] ; i++) + tnl->vtx.attrptr[attr][i-1] = id[i-1]; + } +} + + + + +/* 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 ) +{ + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (tnl->vtx.attrsz[attr] != sz) + _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; + + /* 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 + */ + tnl->vtx.tabfv[attr][sz-1] = fallback_attr_func; + + (*fallback_attr_func)(v); +} + + /* 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. + * 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 @@ -51,7 +335,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * is the job of the chooser function when switching between Color4f * and Color3f. */ -#define ATTRF( ATTR, N, A, B, C, D ) \ +#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); \ @@ -59,75 +346,61 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. 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; \ + 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].ui = tnl->vtx.vertex[i].ui; \ + tnl->vtx.vbptr[i] = tnl->vtx.vertex[i]; \ \ tnl->vtx.vbptr += tnl->vtx.vertex_size; \ \ if (--tnl->vtx.counter == 0) \ - _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); \ + _tnl_wrap_filled_vertex( ctx ); \ } \ 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; \ + 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 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 ) \ -{ \ - ATTR1F( ATTRIB, s ); \ -} \ - \ -static void attrib_##ATTRIB##_1_1( const GLfloat *v ) \ -{ \ - ATTR1F( ATTRIB, v[0] ); \ -} \ - \ -static void attrib_##ATTRIB##_2_0( GLfloat s, GLfloat t ) \ -{ \ - ATTR2F( ATTRIB, s, t ); \ -} \ - \ -static void attrib_##ATTRIB##_2_1( const GLfloat *v ) \ -{ \ - ATTR2F( ATTRIB, v[0], v[1] ); \ -} \ - \ -static void attrib_##ATTRIB##_3_0( GLfloat s, GLfloat t, \ - GLfloat r ) \ -{ \ - ATTR3F( ATTRIB, s, t, r ); \ -} \ - \ -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] ); \ +#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; \ } + + +#define ATTRS( ATTRIB ) \ + ATTRFV( ATTRIB, 1 ) \ + ATTRFV( ATTRIB, 2 ) \ + ATTRFV( ATTRIB, 3 ) \ + ATTRFV( ATTRIB, 4 ) \ + 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 @@ -150,214 +423,46 @@ 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 ) +static void init_attrfv( TNLcontext *tnl ) { - GLuint oldsz = tnl->vtx.attrib[attr].sz; - - _tnl_flush_immediate( ctx ); - - tnl->vtx.attrib[attr].sz = newsz; - /* What else to do here? - */ - - /* 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_wrap_buffers( GLcontext *ctx ) -{ - _tnl_flush_immediate( ctx ); - - /* 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 ); - } - } -} - - - -/* 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. - */ - -/* An active attribute has changed size. - */ -static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - - 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]; - } + if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, tnl->vtx.vertex_size); - /* Reset the dispatch table - aliasing entrypoints are invalidated. - */ - _tnl_reset_attr_dispatch_tab( ctx ); -} - -static int dispatch_offset[TNL_ATTRIB_MAX][4][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; - - /* 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 ); - - - if (attr == 0) - key = tnl->vtx.vertex_size; - else - key = (GLuint)tnl->vtx.attrptr[attr]; - - for (dfn = tnl->vtx.generated[sz-1][v][isvertex]; dfn; dfn = dfn->next) { - if (dfn->key == key) { - ptr = dfn->code; - break; - } - } - - 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 (tnl->vtx.vertex_size) { + GLuint i; - if (ptr == 0) - ptr = fallback_attr_func; - - ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; - - /* 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; - - return ptr; + 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 ); + + for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++) + tnl->vtx.attrsz[i] = 0; + + tnl->vtx.vertex_size = 0; + } } - -/* 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. - * - * Need ATTR1 for use in constructing name of 'attrib_x_y_z' function. - */ -#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; \ -} - -#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) - -/* Not that many entrypoints when it all boils down: - */ -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... +/* 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[COUNT-1][ATTR]( P ); \ + tnl->vtx.tabfv[ATTR][COUNT-1]( P ); \ } while (0) #define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V ) @@ -366,15 +471,7 @@ do { \ #define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V ) #define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) ) -#ifdef USE_X86_ASM -/* Naughty cheat: - */ -#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: - */ + #define DISPATCH_ATTR2F( ATTR, S,T ) \ do { \ GLfloat v[2]; \ @@ -393,8 +490,6 @@ do { \ v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \ DISPATCH_ATTR4FV( ATTR, v ); \ } while (0) -#endif - static void enum_error( void ) @@ -403,136 +498,237 @@ static void enum_error( void ) _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); } -static void op_error( void ) +static void _tnl_Vertex2f( GLfloat x, GLfloat y ) { - GET_CURRENT_CONTEXT( ctx ); - _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ ); + DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y ); } +static void _tnl_Vertex2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v ); +} -/* 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_MultiTexCoord1f( GLenum target, GLfloat s ) +static void _tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z ); +} + +static void _tnl_Vertex3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v ); +} + +static void _tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w ); +} + +static void _tnl_Vertex4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v ); +} + +static void _tnl_TexCoord1f( GLfloat x ) +{ + DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x ); +} + +static void _tnl_TexCoord1fv( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_TexCoord2f( GLfloat x, GLfloat y ) +{ + DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y ); +} + +static void _tnl_TexCoord2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_TexCoord3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z ); +} + +static void _tnl_TexCoord3fv( const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR1FV( attr, &s ); + DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w ); +} + +static void _tnl_TexCoord4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_Normal3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z ); +} + +static void _tnl_Normal3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v ); +} + +static void _tnl_FogCoordfEXT( GLfloat x ) +{ + DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x ); +} + +static void _tnl_FogCoordfvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v ); +} + +static void _tnl_Color3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z ); +} + +static void _tnl_Color3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v ); +} + +static void _tnl_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_COLOR0, x, y, z, w ); +} + +static void _tnl_Color4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_COLOR0, v ); +} + +static void _tnl_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR1, x, y, z ); +} + +static void _tnl_SecondaryColor3fvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR1, v ); +} + +static void _tnl_MultiTexCoord1f( GLenum target, GLfloat x ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR1F( attr, x ); } static void _tnl_MultiTexCoord1fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR1FV( attr, v ); } -static void _tnl_MultiTexCoord2f( GLenum target, GLfloat s, GLfloat t ) +static void _tnl_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR2F( attr, s, t ); + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR2F( attr, x, y ); } static void _tnl_MultiTexCoord2fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR2FV( attr, v ); } -static void _tnl_MultiTexCoord3f( GLenum target, GLfloat s, GLfloat t, - GLfloat r) +static void _tnl_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y, + GLfloat z) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR3F( attr, s, t, r ); + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR3F( attr, x, y, z ); } static void _tnl_MultiTexCoord3fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR3FV( attr, v ); } -static void _tnl_MultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, - GLfloat r, GLfloat q ) +static void _tnl_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR4F( attr, s, t, r, q ); + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR4F( attr, x, y, z, w ); } static void _tnl_MultiTexCoord4fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR4FV( attr, v ); } - -/* 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 x ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR1F( index, s ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR1F( index, x ); else enum_error(); } static void _tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR1FV( index, v ); else enum_error(); } -static void _tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t ) +static void _tnl_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR2F( index, s, t ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR2F( index, x, y ); else enum_error(); } static void _tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR2FV( index, v ); else enum_error(); } -static void _tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t, - GLfloat r ) +static void _tnl_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR3F( index, s, t, r ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR3F( index, x, y, z ); else enum_error(); } static void _tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR3FV( index, v ); else enum_error(); } -static void _tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t, - GLfloat r, GLfloat q ) +static void _tnl_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR4F( index, s, t, r, q ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR4F( index, x, y, z, w ); else enum_error(); } static void _tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR4FV( index, v ); else enum_error(); @@ -549,19 +745,21 @@ static void _tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) * 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. + * + * There is no aliasing of material attributes with other entrypoints. */ #define MAT_ATTR( A, N, params ) \ do { \ - if (tnl->vtx.attrib_sz[A] != N) { \ - tnl_fixup_vertex( ctx, A, N ); \ + if (tnl->vtx.attrsz[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]; \ + 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]; \ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ } \ } while (0) @@ -585,28 +783,39 @@ static void _tnl_Materialfv( GLenum face, GLenum pname, GET_CURRENT_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); + switch (face) { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__); + return; + } + switch (pname) { case GL_EMISSION: - MAT( VERT_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); break; case GL_AMBIENT: - MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); break; case GL_DIFFUSE: - MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); break; case GL_SPECULAR: - MAT( VERT_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); break; case GL_SHININESS: - MAT( VERT_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); break; case GL_COLOR_INDEXES: - MAT( VERT_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); break; case GL_AMBIENT_AND_DIFFUSE: - MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); - MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); break; default: _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); @@ -620,248 +829,313 @@ do { \ GET_CURRENT_CONTEXT( ctx ); \ TNLcontext *tnl = TNL_CONTEXT(ctx); \ \ - if (tnl->vtx.attrib_sz[A] != 1) { \ - tnl_fixup_vertex( ctx, A, 1 ); \ + if (tnl->vtx.attrsz[A] != 1) { \ + _tnl_fixup_vertex( ctx, A, 1 ); \ } \ \ { \ - union uif *dest = tnl->vtx.attrptr[A]; \ - dest[0].ui = IDX; \ + GLfloat *dest = tnl->vtx.attrptr[A]; \ + dest[0] = IDX; \ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ } \ } while (0) -static void _tnl_EdgeFlag( GLboolean f ) +static void _tnl_EdgeFlag( GLboolean b ) { - IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f ); + IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)b ); } -static void _tnl_EdgeFlagv( const GLboolean *f ) +static void _tnl_EdgeFlagv( const GLboolean *v ) { - IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f[0] ); + IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)v[0] ); } -static void _tnl_Indexi( GLint i ) +static void _tnl_Indexf( GLfloat f ) { - IDX_ATTR( VERT_ATTRIB_INDEX, i ); + IDX_ATTR( _TNL_ATTRIB_INDEX, f ); } -static void _tnl_Indexiv( const GLint *i ) +static void _tnl_Indexfv( const GLfloat *v ) { - IDX_ATTR( VERT_ATTRIB_INDEX, i[0] ); + IDX_ATTR( _TNL_ATTRIB_INDEX, v[0] ); } - - -/* EvalCoord needs special treatment as ususal: +/* Eval */ -static void evalcoord( GLfloat a, GLfloat b, GLuint type ) +static void _tnl_EvalCoord1f( GLfloat u ) { -#if 0 - GET_CURRENT_CONTEXT( ctx ); - TNLcontext *tnl = TNL_CONTEXT(ctx); - - /* Initialize the list of eval fixups: - */ - if (!tnl->evalptr) { - init_eval_ptr( ctx ); + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* TODO: use a CHOOSE() function for this: */ + { + GLint i; + if (tnl->vtx.eval.new_state) + _tnl_update_eval( ctx ); + + for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) { + if (tnl->vtx.eval.map1[i].map) + if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map1[i].sz) + _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map1[i].sz ); + } } - /* 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 -} + memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex, + tnl->vtx.vertex_size * sizeof(GLfloat)); + _tnl_do_EvalCoord1f( ctx, u ); -static void _tnl_EvalCoord1f( GLfloat u ) -{ - evalcoord( u, 0, TNL_EVAL_COORD1 ); + memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer, + tnl->vtx.vertex_size * sizeof(GLfloat)); } -static void _tnl_EvalCoord1fv( const GLfloat *v ) +static void _tnl_EvalCoord2f( GLfloat u, GLfloat v ) { - evalcoord( v[0], 0, TNL_EVAL_COORD1 ); + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* TODO: use a CHOOSE() function for this: */ + { + GLint i; + if (tnl->vtx.eval.new_state) + _tnl_update_eval( ctx ); + + for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) { + if (tnl->vtx.eval.map2[i].map) + if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map2[i].sz) + _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map2[i].sz ); + } + + if (ctx->Eval.AutoNormal) + if (tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL] < 3) + _tnl_fixup_vertex( ctx, _TNL_ATTRIB_NORMAL, 3 ); + } + + memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex, + tnl->vtx.vertex_size * sizeof(GLfloat)); + + _tnl_do_EvalCoord2f( ctx, u, v ); + + memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer, + tnl->vtx.vertex_size * sizeof(GLfloat)); } -static void _tnl_EvalCoord2f( GLfloat u, GLfloat v ) +static void _tnl_EvalCoord1fv( const GLfloat *u ) { - evalcoord( u, v, TNL_EVAL_COORD2 ); + _tnl_EvalCoord1f( u[0] ); } -static void _tnl_EvalCoord2fv( const GLfloat *v ) +static void _tnl_EvalCoord2fv( const GLfloat *u ) { - evalcoord( v[0], v[1], TNL_EVAL_COORD2 ); + _tnl_EvalCoord2f( u[0], u[1] ); } static void _tnl_EvalPoint1( GLint i ) { - evalcoord( (GLfloat)i, 0, TNL_EVAL_POINT1 ); + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) / + (GLfloat) ctx->Eval.MapGrid1un); + GLfloat u = i * du + ctx->Eval.MapGrid1u1; + + _tnl_EvalCoord1f( u ); } + static void _tnl_EvalPoint2( GLint i, GLint j ) { - evalcoord( (GLfloat)i, (GLfloat)j, TNL_EVAL_POINT2 ); + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / + (GLfloat) ctx->Eval.MapGrid2un); + GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / + (GLfloat) ctx->Eval.MapGrid2vn); + GLfloat u = i * du + ctx->Eval.MapGrid2u1; + GLfloat v = j * dv + ctx->Eval.MapGrid2v1; + + _tnl_EvalCoord2f( u, v ); } -/* 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. + +/* Build a list of primitives on the fly. Keep + * ctx->Driver.CurrentExecPrimitive uptodate as well. */ 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 (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { + TNLcontext *tnl = TNL_CONTEXT(ctx); + int i; + + if (ctx->NewState) { + _mesa_update_state( ctx ); + ctx->Exec->Begin(mode); + return; + } + +#if 1 + /* Heuristic: attempt to isolate attributes occuring outside + * begin/end pairs. + */ + if (tnl->vtx.vertex_size && !tnl->vtx.attrsz[0]) + _tnl_FlushVertices( ctx, ~0 ); +#endif + + i = tnl->vtx.prim_count++; + tnl->vtx.prim[i].mode = mode | PRIM_BEGIN; + tnl->vtx.prim[i].start = tnl->vtx.initial_counter - tnl->vtx.counter; + tnl->vtx.prim[i].count = 0; - if (tnl->vtx.be_count == TNL_BE_MAX) - _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); + ctx->Driver.CurrentExecPrimitive = mode; + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ ); + } static void _tnl_End( void ) { 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 (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + TNLcontext *tnl = TNL_CONTEXT(ctx); + int idx = tnl->vtx.initial_counter - tnl->vtx.counter; + int i = tnl->vtx.prim_count - 1; - if (tnl->vtx.be_count == TNL_BE_MAX) - _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); -} + tnl->vtx.prim[i].mode |= PRIM_END; + tnl->vtx.prim[i].count = idx - tnl->vtx.prim[i].start; + + ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; + +#if 0 + if (tnl->vtx.counter * 2 > tnl->vtx.initial_counter) + _tnl_FlushVertices( ctx, ~0 ); +#endif + if (tnl->vtx.prim_count == TNL_MAX_PRIM) { +#if 0 + _tnl_FlushVertices( ctx, ~0 ); +#else + _tnl_flush_vtx( ctx ); +#endif + } + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ ); +} +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->EvalCoord1f = _tnl_EvalCoord1f; + vfmt->EvalCoord1fv = _tnl_EvalCoord1fv; + vfmt->EvalCoord2f = _tnl_EvalCoord2f; + 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; + vfmt->EvalMesh2 = _mesa_noop_EvalMesh2; +} -static void _tnl_InitDispatch( struct _glapi_table *tab ) +void _tnl_FlushVertices( GLcontext *ctx, GLuint flags ) { - GLint i; - - /* 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?). - */ - 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; -} - -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) - */ - 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; - } - } - } + TNLcontext *tnl = TNL_CONTEXT(ctx); -#if 0 - if (!getenv("MESA_NO_CODEGEN")) { -#if defined(USE_X86_ASM) - _tnl_InitX86Codegen( gen ); -#endif + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) + return; -#if defined(USE_SSE_ASM) - _tnl_InitSSECodegen( gen ); + if (tnl->vtx.counter != tnl->vtx.initial_counter) { + _tnl_flush_vtx( ctx ); +#if 0 + init_0(tnl); #endif + } -#if defined(USE_3DNOW_ASM) +#if 0 + if (flags & FLUSH_UPDATE_CURRENT) #endif + { + _tnl_copy_to_current( ctx ); -#if defined(USE_SPARC_ASM) -#endif + /* reset attrfv table + */ + init_attrfv( tnl ); + flags |= FLUSH_UPDATE_CURRENT; } -#endif + + ctx->Driver.NeedFlush = 0; +} + +static void _tnl_current_init( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLint i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + tnl->vtx.current[i] = ctx->Current.Attrib[i]; + + for (i = 0; i < MAT_ATTRIB_MAX; i++) + tnl->vtx.current[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = + ctx->Light.Material.Attrib[i]; + + tnl->vtx.current[_TNL_ATTRIB_INDEX] = &ctx->Current.Index; } @@ -870,29 +1144,22 @@ static void _tnl_InitCodegen( GLcontext *ctx ) void _tnl_vtx_init( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - _tnl_InitDispatch( tnl->Exec ); - _tnl_InitCodegen( ctx ); + struct tnl_vertex_arrays *tmp = &tnl->vtx_inputs; + GLuint i; + + for (i = 0; i < _TNL_ATTRIB_INDEX; i++) + _mesa_vector4f_init( &tmp->Attribs[i], 0, 0); + + _tnl_current_init( ctx ); + _tnl_exec_vtxfmt_init( ctx ); + + _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt ); + tnl->vtx.vertex_size = 1; init_attrfv( tnl ); } 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; - } - } - } - } } |