summaryrefslogtreecommitdiff
path: root/src/mesa/tnl/t_vtx_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/tnl/t_vtx_api.c')
-rw-r--r--src/mesa/tnl/t_vtx_api.c1319
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 d734b67dbd..21ec1c9a7b 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 <keith@tungstengraphics.com>
*/
-#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;
- }
- }
- }
- }
}