📄 t_save_api.c
字号:
/* Store the current run of vertices, and emit a GL_END. Emit a
* BEGIN in the new buffer.
*/
if (tnl->save.initial_counter != tnl->save.counter)
_save_wrap_buffers( ctx );
else
assert( tnl->save.copied.nr == 0 );
/* 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.
*/
_save_copy_to_current( ctx );
/* Fix up sizes:
*/
oldsz = tnl->save.attrsz[attr];
tnl->save.attrsz[attr] = newsz;
tnl->save.vertex_size += newsz - oldsz;
tnl->save.counter = ((SAVE_BUFFER_SIZE - tnl->save.vertex_store->used) /
tnl->save.vertex_size);
if (tnl->save.counter > ctx->Const.MaxArrayLockSize )
tnl->save.counter = ctx->Const.MaxArrayLockSize;
tnl->save.initial_counter = tnl->save.counter;
/* Recalculate all the attrptr[] values:
*/
for (i = 0, tmp = tnl->save.vertex ; i < _TNL_ATTRIB_MAX ; i++) {
if (tnl->save.attrsz[i]) {
tnl->save.attrptr[i] = tmp;
tmp += tnl->save.attrsz[i];
}
else
tnl->save.attrptr[i] = NULL; /* will not be dereferenced. */
}
/* Copy from current to repopulate the vertex with correct values.
*/
_save_copy_from_current( ctx );
/* Replay stored vertices to translate them to new format here.
*
* If there are copied vertices and the new (upgraded) attribute
* has not been defined before, this list is somewhat degenerate,
* and will need fixup at runtime.
*/
if (tnl->save.copied.nr)
{
GLfloat *data = tnl->save.copied.buffer;
GLfloat *dest = tnl->save.buffer;
GLuint j;
/* Need to note this and fix up at runtime (or loopback):
*/
if (tnl->save.currentsz[attr][0] == 0) {
assert(oldsz == 0);
tnl->save.dangling_attr_ref = GL_TRUE;
/* _mesa_debug(NULL, "_save_upgrade_vertex: dangling reference attr %d\n", */
/* attr); */
#if 0
/* The current strategy is to punt these degenerate cases
* through _tnl_loopback_vertex_list(), a lower-performance
* option. To minimize the impact of this, artificially
* reduce the size of this vertex_list.
*/
if (t->save.counter > 10) {
t->save.initial_counter = 10;
t->save.counter = 10;
}
#endif
}
for (i = 0 ; i < tnl->save.copied.nr ; i++) {
for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) {
if (tnl->save.attrsz[j]) {
if (j == attr) {
if (oldsz) {
COPY_CLEAN_4V( dest, oldsz, data );
data += oldsz;
dest += newsz;
}
else {
COPY_SZ_4V( dest, newsz, tnl->save.current[attr] );
dest += newsz;
}
}
else {
GLint sz = tnl->save.attrsz[j];
COPY_SZ_4V( dest, sz, data );
data += sz;
dest += sz;
}
}
}
}
tnl->save.vbptr = dest;
tnl->save.counter -= tnl->save.copied.nr;
}
}
/* 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 (*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);
static GLfloat id[4] = { 0, 0, 0, 1 };
int i;
if (tnl->save.attrsz[attr] < sz) {
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
*/
_save_upgrade_vertex( ctx, attr, sz );
}
else {
/* New size is equal or smaller - just need to fill in some
* zeros.
*/
for (i = sz ; i <= tnl->save.attrsz[attr] ; i++)
tnl->save.attrptr[attr][i-1] = id[i-1];
}
/* Reset any active pointers for this attribute
*/
tnl->save.tabfv[attr][0] = choose1;
tnl->save.tabfv[attr][1] = choose2;
tnl->save.tabfv[attr][2] = choose3;
tnl->save.tabfv[attr][3] = choose4;
/* Update the secondary dispatch table with the new function
*/
tnl->save.tabfv[attr][sz-1] = attr_func;
(*attr_func)(v);
}
/* Only one size for each attribute may be active at once. Eg. if
* Color3f is installed/active, then Color4f may not be, even if the
* vertex actually contains 4 color coordinates. This is because the
* 3f version won't otherwise set color[3] to 1.0 -- this is the job
* of the chooser function when switching between Color4f and Color3f.
*/
#define ATTRFV( ATTR, N ) \
static void save_choose_##ATTR##_##N( const GLfloat *v ); \
\
static void save_attrib_##ATTR##_##N( const GLfloat *v ) \
{ \
GET_CURRENT_CONTEXT( ctx ); \
TNLcontext *tnl = TNL_CONTEXT(ctx); \
\
if ((ATTR) == 0) { \
GLuint i; \
\
if (N>0) tnl->save.vbptr[0] = v[0]; \
if (N>1) tnl->save.vbptr[1] = v[1]; \
if (N>2) tnl->save.vbptr[2] = v[2]; \
if (N>3) tnl->save.vbptr[3] = v[3]; \
\
for (i = N; i < tnl->save.vertex_size; i++) \
tnl->save.vbptr[i] = tnl->save.vertex[i]; \
\
tnl->save.vbptr += tnl->save.vertex_size; \
\
if (--tnl->save.counter == 0) \
_save_wrap_filled_vertex( ctx ); \
} \
else { \
GLfloat *dest = tnl->save.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 CHOOSE( ATTR, N ) \
static void save_choose_##ATTR##_##N( const GLfloat *v ) \
{ \
do_choose(ATTR, N, \
save_attrib_##ATTR##_##N, \
save_choose_##ATTR##_1, \
save_choose_##ATTR##_2, \
save_choose_##ATTR##_3, \
save_choose_##ATTR##_4, \
v ); \
}
#define INIT(ATTR) \
static void save_init_##ATTR( TNLcontext *tnl ) \
{ \
tnl->save.tabfv[ATTR][0] = save_choose_##ATTR##_1; \
tnl->save.tabfv[ATTR][1] = save_choose_##ATTR##_2; \
tnl->save.tabfv[ATTR][2] = save_choose_##ATTR##_3; \
tnl->save.tabfv[ATTR][3] = save_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
* elsewhere.
*/
ATTRS( 0 )
ATTRS( 1 )
ATTRS( 2 )
ATTRS( 3 )
ATTRS( 4 )
ATTRS( 5 )
ATTRS( 6 )
ATTRS( 7 )
ATTRS( 8 )
ATTRS( 9 )
ATTRS( 10 )
ATTRS( 11 )
ATTRS( 12 )
ATTRS( 13 )
ATTRS( 14 )
ATTRS( 15 )
static void _save_reset_vertex( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
save_init_0( tnl );
save_init_1( tnl );
save_init_2( tnl );
save_init_3( tnl );
save_init_4( tnl );
save_init_5( tnl );
save_init_6( tnl );
save_init_7( tnl );
save_init_8( tnl );
save_init_9( tnl );
save_init_10( tnl );
save_init_11( tnl );
save_init_12( tnl );
save_init_13( tnl );
save_init_14( tnl );
save_init_15( tnl );
for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
tnl->save.attrsz[i] = 0;
tnl->save.vertex_size = 0;
tnl->save.have_materials = 0;
_save_reset_counters( ctx );
}
/* Cope with aliasing of classic Vertex, Normal, etc. and the fan-out
* of glMultTexCoord and glProgramParamterNV by routing all these
* through a second level dispatch table.
*/
#define DISPATCH_ATTRFV( ATTR, COUNT, P ) \
do { \
GET_CURRENT_CONTEXT( ctx ); \
TNLcontext *tnl = TNL_CONTEXT(ctx); \
tnl->save.tabfv[ATTR][COUNT-1]( P ); \
} while (0)
#define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V )
#define DISPATCH_ATTR2FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 2, V )
#define DISPATCH_ATTR3FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 3, V )
#define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V )
#define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) )
#if defined(USE_X86_ASM) && 0 /* will break register calling convention */
/* 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]; \
v[0] = S; v[1] = T; \
DISPATCH_ATTR2FV( ATTR, v ); \
} while (0)
#define DISPATCH_ATTR3F( ATTR, S,T,R ) \
do { \
GLfloat v[3]; \
v[0] = S; v[1] = T; v[2] = R; \
DISPATCH_ATTR3FV( ATTR, v ); \
} while (0)
#define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) \
do { \
GLfloat v[4]; \
v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \
DISPATCH_ATTR4FV( ATTR, v ); \
} while (0)
#endif
static void enum_error( void )
{
GET_CURRENT_CONTEXT( ctx );
_mesa_compile_error( ctx, GL_INVALID_ENUM, "glVertexAttrib" );
}
static void GLAPIENTRY _save_Vertex2f( GLfloat x, GLfloat y )
{
DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y );
}
static void GLAPIENTRY _save_Vertex2fv( const GLfloat *v )
{
DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v );
}
static void GLAPIENTRY _save_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
{
DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z );
}
static void GLAPIENTRY _save_Vertex3fv( const GLfloat *v )
{
DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v );
}
static void GLAPIENTRY _save_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
{
DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w );
}
static void GLAPIENTRY _save_Vertex4fv( const GLfloat *v )
{
DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v );
}
static void GLAPIENTRY _save_TexCoord1f( GLfloat x )
{
DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x );
}
static void GLAPIENTRY _save_TexCoord1fv( const GLfloat *v )
{
DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v );
}
static void GLAPIENTRY _save_TexCoord2f( GLfloat x, GLfloat y )
{
DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y );
}
static void GLAPIENTRY _save_TexCoord2fv( const GLfloat *v )
{
DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v );
}
static void GLAPIENTRY _save_TexCoord3f( GLfloat x, GLfloat y, GLfloat z )
{
DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z );
}
static void GLAPIENTRY _save_TexCoord3fv( const GLfloat *v )
{
DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v );
}
static void GLAPIENTRY _save_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
{
DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w );
}
static void GLAPIENTRY _save_TexCoord4fv( const GLfloat *v )
{
DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v );
}
static void GLAPIENTRY _save_Normal3f( GLfloat x, GLfloat y, GLfloat z )
{
DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z );
}
static void GLAPIENTRY _save_Normal3fv( const GLfloat *v )
{
DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v );
}
static void GLAPIENTRY _save_FogCoordfEXT( GLfloat x )
{
DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x );
}
static void GLAPIENTRY _save_FogCoordfvEXT( const GLfloat *v )
{
DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v );
}
static void GLAPIENTRY _save_Color3f( GLfloat x, GLfloat y, GLfloat z )
{
DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z );
}
static void GLAPIENTRY _save_Color3fv( const GLfloat *v )
{
DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -