📄 t_vtx_api.c
字号:
{
GLuint i;
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
if (tnl->vtx.attrsz[i]) {
GLint j = tnl->vtx.attrsz[i] - 1;
tnl->vtx.attrsz[i] = 0;
if (i < _TNL_MAX_ATTR_CODEGEN) {
while (j >= 0) {
tnl->vtx.tabfv[i][j] = choose[i][j];
j--;
}
}
}
tnl->vtx.vertex_size = 0;
tnl->vtx.have_materials = 0;
}
/* Materials:
*
* These are treated as per-vertex attributes, at indices above where
* the NV_vertex_program leaves off. There are a lot of good things
* about treating materials this way.
*
* However: I don't want to double the number of generated functions
* just to cope with this, so I unroll the 'C' varients of CHOOSE and
* ATTRF into this function, and dispense with codegen and
* second-level dispatch.
*
* There is no aliasing of material attributes with other entrypoints.
*/
#define OTHER_ATTR( A, N, params ) \
do { \
if (tnl->vtx.attrsz[A] != N) { \
_tnl_fixup_vertex( ctx, A, N ); \
} \
\
{ \
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]; \
} \
} while (0)
#define MAT( ATTR, N, face, params ) \
do { \
if (face != GL_BACK) \
OTHER_ATTR( ATTR, N, params ); /* front */ \
if (face != GL_FRONT) \
OTHER_ATTR( ATTR + 1, N, params ); /* back */ \
} while (0)
/* Colormaterial is dealt with later on.
*/
static void GLAPIENTRY _tnl_Materialfv( GLenum face, GLenum pname,
const GLfloat *params )
{
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, "glMaterialfv" );
return;
}
switch (pname) {
case GL_EMISSION:
MAT( _TNL_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
break;
case GL_AMBIENT:
MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
break;
case GL_DIFFUSE:
MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
break;
case GL_SPECULAR:
MAT( _TNL_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
break;
case GL_SHININESS:
MAT( _TNL_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
break;
case GL_COLOR_INDEXES:
MAT( _TNL_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
break;
case GL_AMBIENT_AND_DIFFUSE:
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, "glMaterialfv" );
return;
}
tnl->vtx.have_materials = GL_TRUE;
}
static void GLAPIENTRY _tnl_EdgeFlag( GLboolean b )
{
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLfloat f = (GLfloat)b;
OTHER_ATTR( _TNL_ATTRIB_EDGEFLAG, 1, &f );
}
static void GLAPIENTRY _tnl_EdgeFlagv( const GLboolean *v )
{
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLfloat f = (GLfloat)v[0];
OTHER_ATTR( _TNL_ATTRIB_EDGEFLAG, 1, &f );
}
static void GLAPIENTRY _tnl_Indexf( GLfloat f )
{
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
OTHER_ATTR( _TNL_ATTRIB_INDEX, 1, &f );
}
static void GLAPIENTRY _tnl_Indexfv( const GLfloat *v )
{
GET_CURRENT_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
OTHER_ATTR( _TNL_ATTRIB_INDEX, 1, v );
}
/* Eval
*/
static void GLAPIENTRY _tnl_EvalCoord1f( GLfloat u )
{
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 );
}
}
_mesa_memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex,
tnl->vtx.vertex_size * sizeof(GLfloat));
_tnl_do_EvalCoord1f( ctx, u );
_mesa_memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer,
tnl->vtx.vertex_size * sizeof(GLfloat));
}
static void GLAPIENTRY _tnl_EvalCoord2f( GLfloat u, GLfloat v )
{
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 );
}
_mesa_memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex,
tnl->vtx.vertex_size * sizeof(GLfloat));
_tnl_do_EvalCoord2f( ctx, u, v );
_mesa_memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer,
tnl->vtx.vertex_size * sizeof(GLfloat));
}
static void GLAPIENTRY _tnl_EvalCoord1fv( const GLfloat *u )
{
_tnl_EvalCoord1f( u[0] );
}
static void GLAPIENTRY _tnl_EvalCoord2fv( const GLfloat *u )
{
_tnl_EvalCoord2f( u[0], u[1] );
}
static void GLAPIENTRY _tnl_EvalPoint1( GLint i )
{
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 GLAPIENTRY _tnl_EvalPoint2( GLint i, GLint j )
{
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 );
}
/* Build a list of primitives on the fly. Keep
* ctx->Driver.CurrentExecPrimitive uptodate as well.
*/
static void GLAPIENTRY _tnl_Begin( GLenum mode )
{
GET_CURRENT_CONTEXT( ctx );
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 )))
CALL_Begin(ctx->Exec, (mode));
return;
}
/* Heuristic: attempt to isolate attributes occuring outside
* begin/end pairs.
*/
if (tnl->vtx.vertex_size && !tnl->vtx.attrsz[0])
_tnl_FlushVertices( ctx, ~0 );
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;
ctx->Driver.CurrentExecPrimitive = mode;
}
else
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
}
static void GLAPIENTRY _tnl_End( void )
{
GET_CURRENT_CONTEXT( ctx );
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;
tnl->vtx.prim[i].mode |= PRIM_END;
tnl->vtx.prim[i].count = idx - tnl->vtx.prim[i].start;
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
/* Two choices which effect the way vertex attributes are
* carried over (or not) between adjacent primitives.
*/
#if 0
if (tnl->vtx.prim_count == TNL_MAX_PRIM)
_tnl_FlushVertices( ctx, ~0 );
#else
if (tnl->vtx.prim_count == TNL_MAX_PRIM)
_tnl_flush_vtx( ctx );
#endif
}
else
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
}
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->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->Indexf = _tnl_Indexf;
vfmt->Indexfv = _tnl_Indexfv;
vfmt->Materialfv = _tnl_Materialfv;
vfmt->Rectf = _mesa_noop_Rectf;
vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
}
void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
(void) flags;
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
return;
if (tnl->vtx.counter != tnl->vtx.initial_counter) {
_tnl_flush_vtx( ctx );
}
if (tnl->vtx.vertex_size) {
_tnl_copy_to_current( ctx );
reset_attrfv( tnl );
}
ctx->Driver.NeedFlush = 0;
}
static void _tnl_current_init( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLint i;
/* setup the pointers for the typical 16 vertex attributes */
for (i = 0; i < VERT_ATTRIB_MAX; i++)
tnl->vtx.current[i] = ctx->Current.Attrib[i];
/* setup pointers for the 12 material attributes */
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;
tnl->vtx.current[_TNL_ATTRIB_EDGEFLAG] = &tnl->vtx.CurrentFloatEdgeFlag;
}
static struct _tnl_dynfn *no_codegen( GLcontext *ctx, int key )
{
(void) ctx; (void) key;
return NULL;
}
void _tnl_vtx_init( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct tnl_vertex_arrays *tmp = &tnl->vtx_inputs;
GLuint i;
static int firsttime = 1;
if (firsttime) {
firsttime = 0;
INIT_CHOOSERS( 0 );
INIT_CHOOSERS( 1 );
INIT_CHOOSERS( 2 );
INIT_CHOOSERS( 3 );
INIT_CHOOSERS( 4 );
INIT_CHOOSERS( 5 );
INIT_CHOOSERS( 6 );
INIT_CHOOSERS( 7 );
INIT_CHOOSERS( 8 );
INIT_CHOOSERS( 9 );
INIT_CHOOSERS( 10 );
INIT_CHOOSERS( 11 );
INIT_CHOOSERS( 12 );
INIT_CHOOSERS( 13 );
INIT_CHOOSERS( 14 );
INIT_CHOOSERS( 15 );
choose[ERROR_ATTRIB][0] = error_attrib;
choose[ERROR_ATTRIB][1] = error_attrib;
choose[ERROR_ATTRIB][2] = error_attrib;
choose[ERROR_ATTRIB][3] = error_attrib;
#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, NULL);
for (i = 0; i < 4; i++) {
make_empty_list( &tnl->vtx.cache.Vertex[i] );
make_empty_list( &tnl->vtx.cache.Attribute[i] );
tnl->vtx.gen.Vertex[i] = no_codegen;
tnl->vtx.gen.Attribute[i] = no_codegen;
}
#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 );
memcpy( tnl->vtx.tabfv, choose, sizeof(choose) );
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
tnl->vtx.attrsz[i] = 0;
tnl->vtx.vertex_size = 0;
tnl->vtx.have_materials = 0;
}
static void free_funcs( struct _tnl_dynfn *l )
{
struct _tnl_dynfn *f, *tmp;
foreach_s (f, tmp, l) {
remove_from_list( f );
ALIGN_FREE( f->code );
FREE( f );
}
}
void _tnl_vtx_destroy( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
for (i = 0; i < 4; i++) {
free_funcs( &tnl->vtx.cache.Vertex[i] );
free_funcs( &tnl->vtx.cache.Attribute[i] );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -