#include "t_vtx_api.h"
#include "simple_list.h"
+#include "dispatch.h"
+
static void reset_attrfv( TNLcontext *tnl );
-static attrfv_func choose[_TNL_MAX_ATTR_CODEGEN+1][4]; /* +1 for ERROR_ATTRIB */
-static attrfv_func generic_attr_func[_TNL_MAX_ATTR_CODEGEN][4];
+static tnl_attrfv_func choose[_TNL_MAX_ATTR_CODEGEN+1][4]; /* +1 for ERROR_ATTRIB */
+static tnl_attrfv_func generic_attr_func[_TNL_MAX_ATTR_CODEGEN][4];
/* Close off the last primitive, execute the buffer, restart the
}
else {
GLuint last_prim = tnl->vtx.prim[tnl->vtx.prim_count-1].mode;
- GLuint last_count = tnl->vtx.prim[tnl->vtx.prim_count-1].count;
+ GLuint last_count;
if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
GLint i = tnl->vtx.prim_count - 1;
tnl->vtx.prim[i].start);
}
+ last_count = tnl->vtx.prim[tnl->vtx.prim_count-1].count;
+
/* Execute the buffer and save copied vertices.
*/
if (tnl->vtx.counter != tnl->vtx.initial_counter)
/* Deal with buffer wrapping where provoked by the vertex buffer
* filling up, as opposed to upgrade_vertex().
+ *
+ * Make it GLAPIENTRY, so we can tail from the codegen'ed Vertex*fv
*/
-void _tnl_wrap_filled_vertex( GLcontext *ctx )
+void GLAPIENTRY _tnl_wrap_filled_vertex( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLfloat *data = tnl->vtx.copied.buffer;
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
- for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++)
+ for (i = _TNL_ATTRIB_POS+1 ; i < _TNL_ATTRIB_INDEX ; i++) {
if (tnl->vtx.attrsz[i]) {
/* Note: the tnl->vtx.current[i] pointers points to
* the ctx->Current fields. The first 16 or so, anyway.
*/
- ASSIGN_4V( tnl->vtx.current[i], 0, 0, 0, 1 );
- COPY_SZ_4V(tnl->vtx.current[i],
+ COPY_CLEAN_4V(tnl->vtx.current[i],
tnl->vtx.attrsz[i],
tnl->vtx.attrptr[i]);
}
+ }
- /* Edgeflag requires special treatment:
+ /* color index is special (it's not a float[4] so COPY_CLEAN_4V above
+ * will trash adjacent memory!)
*/
- if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG])
- ctx->Current.EdgeFlag =
- (tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0);
+ if (tnl->vtx.attrsz[_TNL_ATTRIB_INDEX]) {
+ ctx->Current.Index = tnl->vtx.attrptr[_TNL_ATTRIB_INDEX][0];
+ }
+ /* Edgeflag requires additional treatment:
+ */
+ if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) {
+ ctx->Current.EdgeFlag =
+ (tnl->vtx.CurrentFloatEdgeFlag == 1.0);
+ }
/* Colormaterial -- this kindof sucks.
*/
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLint i;
- for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++)
+ /* Edgeflag requires additional treatment:
+ */
+ tnl->vtx.CurrentFloatEdgeFlag =
+ (GLfloat)ctx->Current.EdgeFlag;
+
+ for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_MAX ; 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];
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;
}
tmp += tnl->vtx.attrsz[i];
}
else
- tnl->vtx.attrptr[i] = 0; /* will not be dereferenced */
+ tnl->vtx.attrptr[i] = NULL; /* will not be dereferenced */
}
/* Copy from current to repopulate the vertex with correct values.
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;
+ if (oldsz) {
+ COPY_CLEAN_4V( dest, oldsz, data );
+ data += oldsz;
+ dest += newsz;
+ } else {
+ COPY_SZ_4V( dest, newsz, tnl->vtx.current[j] );
+ dest += newsz;
+ }
}
else {
GLuint sz = tnl->vtx.attrsz[j];
for (i = sz ; i <= tnl->vtx.attrsz[attr] ; i++)
tnl->vtx.attrptr[attr][i-1] = id[i-1];
}
+
+ /* Does setting NeedFlush belong here? Necessitates resetting
+ * vtxfmt on each flush (otherwise flags won't get reset
+ * afterwards).
+ */
+ if (attr == 0)
+ ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ else
+ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
}
+#ifdef USE_X86_ASM
static struct _tnl_dynfn *lookup( struct _tnl_dynfn *l, GLuint key )
{
return f;
}
- return 0;
+ return NULL;
}
-static attrfv_func do_codegen( GLcontext *ctx, GLuint attr, GLuint sz )
+static tnl_attrfv_func do_codegen( GLcontext *ctx, GLuint attr, GLuint sz )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct _tnl_dynfn *dfn = 0;
+ struct _tnl_dynfn *dfn = NULL;
if (attr == 0) {
GLuint key = tnl->vtx.vertex_size;
}
if (dfn)
- return (attrfv_func) dfn->code;
+ return *(tnl_attrfv_func *) &dfn->code;
else
- return 0;
+ return NULL;
}
+#endif /* USE_X86_ASM */
+
/* Helper function for 'CHOOSE' macro. Do what's necessary when an
* entrypoint is called for the first time.
*/
-static attrfv_func do_choose( GLuint attr, GLuint sz )
+static tnl_attrfv_func do_choose( GLuint attr, GLuint sz )
{
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
_tnl_fixup_vertex( ctx, attr, sz );
- /* Does setting NeedFlush belong here? Necessitates resetting
- * vtxfmt on each flush (otherwise flags won't get reset
- * afterwards).
- */
- if (attr == 0)
- ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- else
- ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
}
/* Try to use codegen:
- */
+ */
+#ifdef USE_X86_ASM
if (tnl->AllowCodegen)
tnl->vtx.tabfv[attr][sz-1] = do_codegen( ctx, attr, sz );
else
- tnl->vtx.tabfv[attr][sz-1] = 0;
+#endif
+ tnl->vtx.tabfv[attr][sz-1] = NULL;
/* Else use generic version:
*/
#define CHOOSE( ATTR, N ) \
static void choose_##ATTR##_##N( const GLfloat *v ) \
{ \
- attrfv_func f = do_choose(ATTR, N); \
+ tnl_attrfv_func f = do_choose(ATTR, N); \
f( v ); \
}
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
if (tnl->vtx.attrsz[i]) {
- GLuint j = tnl->vtx.attrsz[i] - 1;
+ GLint j = tnl->vtx.attrsz[i] - 1;
tnl->vtx.attrsz[i] = 0;
- if (i < _TNL_MAX_ATTR_CODEGEN)
- tnl->vtx.tabfv[i][j] = choose[i][j];
+ if (i < _TNL_MAX_ATTR_CODEGEN) {
+ while (j >= 0) {
+ tnl->vtx.tabfv[i][j] = choose[i][j];
+ j--;
+ }
+ }
}
tnl->vtx.vertex_size = 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)
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)
+ if (tnl->vtx.attrsz[i] != tnl->vtx.eval.map1[i].sz)
_tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map1[i].sz );
}
}
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)
+ 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)
+ if (tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL] != 3)
_tnl_fixup_vertex( ctx, _TNL_ATTRIB_NORMAL, 3 );
}
{
GET_CURRENT_CONTEXT( ctx );
- if ((ctx->VertexProgram.Enabled
- && !ctx->VertexProgram.Current->Instructions) ||
- (ctx->FragmentProgram.Enabled
- && !ctx->FragmentProgram.Current->Instructions)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBegin (invalid vertex/fragment program)");
- return;
- }
-
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
TNLcontext *tnl = TNL_CONTEXT(ctx);
int i;
if (ctx->NewState) {
_mesa_update_state( ctx );
+
+ if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
+ (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBegin (invalid vertex/fragment program)");
+ return;
+ }
+
if (!(tnl->Driver.NotifyBegin &&
tnl->Driver.NotifyBegin( ctx, mode )))
- ctx->Exec->Begin(mode);
+ CALL_Begin(ctx->Exec, (mode));
return;
}
void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
+ (void) flags;
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
return;
ctx->Light.Material.Attrib[i];
tnl->vtx.current[_TNL_ATTRIB_INDEX] = &ctx->Current.Index;
+ tnl->vtx.current[_TNL_ATTRIB_EDGEFLAG] = &tnl->vtx.CurrentFloatEdgeFlag;
}
static struct _tnl_dynfn *no_codegen( GLcontext *ctx, int key )
{
- return 0;
+ (void) ctx; (void) key;
+ return NULL;
}
void _tnl_vtx_init( GLcontext *ctx )
choose[ERROR_ATTRIB][2] = error_attrib;
choose[ERROR_ATTRIB][3] = error_attrib;
+#ifdef USE_X86_ASM
if (tnl->AllowCodegen) {
_tnl_x86choosers(choose, do_choose); /* x86 INIT_CHOOSERS */
}
+#endif
_tnl_generic_attr_table_init( generic_attr_func );
}
for (i = 0; i < _TNL_ATTRIB_INDEX; i++)
- _mesa_vector4f_init( &tmp->Attribs[i], 0, 0);
+ _mesa_vector4f_init( &tmp->Attribs[i], 0, NULL);
for (i = 0; i < 4; i++) {
make_empty_list( &tnl->vtx.cache.Vertex[i] );
tnl->vtx.gen.Attribute[i] = no_codegen;
}
+#ifdef USE_X86_ASM
_tnl_InitX86Codegen( &tnl->vtx.gen );
+#endif
_tnl_current_init( ctx );
_tnl_exec_vtxfmt_init( ctx );
_tnl_generic_exec_vtxfmt_init( ctx );
+#ifdef USE_X86_ASM
if (tnl->AllowCodegen) {
_tnl_x86_exec_vtxfmt_init( ctx ); /* x86 DISPATCH_ATTRFV */
}
+#endif
_mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt );