mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-04 22:10:11 +01:00
Added a TNL pipeline stage that normalizes texture coordinates as a
workaround for bad Savage hardware interpolation of big texture coordinates.
This commit is contained in:
parent
c403bcb8a7
commit
0d39c4ebc9
2 changed files with 203 additions and 1 deletions
|
|
@ -109,6 +109,22 @@ static const char *const card_extensions[] =
|
|||
NULL
|
||||
};
|
||||
|
||||
extern const struct tnl_pipeline_stage _savage_texnorm_stage;
|
||||
|
||||
static const struct tnl_pipeline_stage *savage_pipeline[] = {
|
||||
|
||||
&_tnl_vertex_transform_stage,
|
||||
&_tnl_normal_transform_stage,
|
||||
&_tnl_lighting_stage,
|
||||
&_tnl_fog_coordinate_stage,
|
||||
&_tnl_texgen_stage,
|
||||
&_tnl_texture_transform_stage,
|
||||
&_savage_texnorm_stage,
|
||||
&_tnl_render_stage,
|
||||
0,
|
||||
};
|
||||
|
||||
|
||||
/* this is first function called in dirver*/
|
||||
|
||||
static GLboolean
|
||||
|
|
@ -455,7 +471,7 @@ savageCreateContext( const __GLcontextModes *mesaVis,
|
|||
|
||||
/* Install the customized pipeline:
|
||||
*/
|
||||
#if 0
|
||||
#if 1
|
||||
_tnl_destroy_pipeline( ctx );
|
||||
_tnl_install_pipeline( ctx, savage_pipeline );
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -911,3 +911,189 @@ void savageInitTriFuncs( GLcontext *ctx )
|
|||
|
||||
SAVAGE_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Pipeline stage for texture coordinate normalization
|
||||
* This should probably go somewhere else.
|
||||
***/
|
||||
struct texnorm_stage_data {
|
||||
GLvector4f texcoord[MAX_TEXTURE_UNITS];
|
||||
};
|
||||
|
||||
#define TEXNORM_STAGE_DATA(stage) ((struct texnorm_stage_data *)stage->privatePtr)
|
||||
|
||||
|
||||
static GLboolean run_texnorm_stage( GLcontext *ctx,
|
||||
struct tnl_pipeline_stage *stage )
|
||||
{
|
||||
struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage);
|
||||
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
GLuint i;
|
||||
|
||||
if (imesa->Fallback)
|
||||
return GL_TRUE;
|
||||
|
||||
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
|
||||
if (!(stage->inputs & stage->changed_inputs & VERT_BIT_TEX(i)))
|
||||
continue;
|
||||
|
||||
GLuint reallyEnabled = ctx->Texture.Unit[i]._ReallyEnabled;
|
||||
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
|
||||
GLboolean normalizeS = (texObj->WrapS == GL_REPEAT);
|
||||
GLboolean normalizeT = (reallyEnabled & TEXTURE_2D_BIT) &&
|
||||
(texObj->WrapT == GL_REPEAT);
|
||||
GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data;
|
||||
GLint instride = VB->TexCoordPtr[i]->stride;
|
||||
GLfloat (*out)[4] = store->texcoord[i].data;
|
||||
GLint j;
|
||||
|
||||
if (normalizeS && normalizeT) {
|
||||
/* determine extreme values in S and T */
|
||||
GLfloat minS = in[0], maxS = in[0], minT = in[1], maxT = in[1];
|
||||
GLfloat correctionS, correctionT;
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
for (j = 1; j < VB->Count; ++j) {
|
||||
if (in[0] < minS) minS = in[0];
|
||||
else if (in[0] > maxS) maxS = in[0];
|
||||
if (in[1] < minT) minT = in[1];
|
||||
else if (in[1] > maxT) maxT = in[1];
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
}
|
||||
correctionS = -floor((minS + maxS) * 0.5 + 0.5);
|
||||
correctionT = -floor((minT + maxT) * 0.5 + 0.5);
|
||||
in = (GLfloat *)VB->TexCoordPtr[i]->data;
|
||||
for (j = 0; j < VB->Count; ++j) {
|
||||
out[j][0] = in[0] + correctionS;
|
||||
out[j][1] = in[1] + correctionT;
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
}
|
||||
} else if (normalizeS) {
|
||||
/* determine extreme values in S */
|
||||
GLfloat minS = in[0], maxS = in[0];
|
||||
GLfloat correctionS;
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
for (j = 1; j < VB->Count; ++j) {
|
||||
if (in[0] < minS) minS = in[0];
|
||||
else if (in[0] > maxS) maxS = in[0];
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
}
|
||||
correctionS = -floor((minS + maxS) * 0.5 + 0.5);
|
||||
in = (GLfloat *)VB->TexCoordPtr[i]->data;
|
||||
if (reallyEnabled & TEXTURE_2D_BIT) {
|
||||
for (j = 0; j < VB->Count; ++j) {
|
||||
out[j][0] = in[0] + correctionS;
|
||||
out[j][1] = in[1];
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < VB->Count; ++j) {
|
||||
out[j][0] = in[0] + correctionS;
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
}
|
||||
}
|
||||
} else if (normalizeT) {
|
||||
/* determine extreme values in T */
|
||||
GLfloat minT = in[1], maxT = in[1];
|
||||
GLfloat correctionT;
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
for (j = 1; j < VB->Count; ++j) {
|
||||
if (in[1] < minT) minT = in[1];
|
||||
else if (in[1] > maxT) maxT = in[1];
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
}
|
||||
correctionT = -floor((minT + maxT) * 0.5 + 0.5);
|
||||
in = (GLfloat *)VB->TexCoordPtr[i]->data;
|
||||
for (j = 0; j < VB->Count; ++j) {
|
||||
out[j][0] = in[0];
|
||||
out[j][1] = in[1] + correctionT;
|
||||
in = (GLfloat *)((GLubyte *)in + instride);
|
||||
}
|
||||
}
|
||||
|
||||
if (normalizeS || normalizeT)
|
||||
VB->AttribPtr[VERT_ATTRIB_TEX0+i] = VB->TexCoordPtr[i] = &store->texcoord[i];
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Called the first time stage->run() is invoked.
|
||||
*/
|
||||
static GLboolean alloc_texnorm_data( GLcontext *ctx,
|
||||
struct tnl_pipeline_stage *stage )
|
||||
{
|
||||
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
||||
struct texnorm_stage_data *store;
|
||||
GLuint i;
|
||||
|
||||
stage->privatePtr = CALLOC(sizeof(*store));
|
||||
store = TEXNORM_STAGE_DATA(stage);
|
||||
if (!store)
|
||||
return GL_FALSE;
|
||||
|
||||
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
|
||||
_mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
|
||||
|
||||
/* Now run the stage.
|
||||
*/
|
||||
stage->run = run_texnorm_stage;
|
||||
return stage->run( ctx, stage );
|
||||
}
|
||||
|
||||
|
||||
static void check_texnorm( GLcontext *ctx,
|
||||
struct tnl_pipeline_stage *stage )
|
||||
{
|
||||
GLuint flags = 0;
|
||||
|
||||
if (((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
|
||||
(ctx->Texture.Unit[0]._Current->WrapS == GL_REPEAT)) ||
|
||||
((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) &&
|
||||
(ctx->Texture.Unit[0]._Current->WrapT == GL_REPEAT)))
|
||||
flags |= VERT_BIT_TEX0;
|
||||
|
||||
if (((ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
|
||||
(ctx->Texture.Unit[1]._Current->WrapS == GL_REPEAT)) ||
|
||||
((ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT) &&
|
||||
(ctx->Texture.Unit[1]._Current->WrapT == GL_REPEAT)))
|
||||
flags |= VERT_BIT_TEX1;
|
||||
|
||||
stage->inputs = flags;
|
||||
stage->outputs = flags;
|
||||
stage->active = (flags != 0);
|
||||
}
|
||||
|
||||
|
||||
static void free_texnorm_data( struct tnl_pipeline_stage *stage )
|
||||
{
|
||||
struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage);
|
||||
GLuint i;
|
||||
|
||||
if (store) {
|
||||
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
|
||||
if (store->texcoord[i].data)
|
||||
_mesa_vector4f_free( &store->texcoord[i] );
|
||||
FREE( store );
|
||||
stage->privatePtr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const struct tnl_pipeline_stage _savage_texnorm_stage =
|
||||
{
|
||||
"savage texture coordinate normalization stage", /* name */
|
||||
_NEW_TEXTURE, /* check_state */
|
||||
_NEW_TEXTURE, /* run_state */
|
||||
GL_TRUE, /* active? */
|
||||
0, /* inputs */
|
||||
0, /* outputs */
|
||||
0, /* changed_inputs */
|
||||
NULL, /* private data */
|
||||
free_texnorm_data, /* destructor */
|
||||
check_texnorm, /* check */
|
||||
alloc_texnorm_data, /* run -- initially set to init */
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue