diff options
author | Felix Kuehling <[email protected]> | 2004-12-17 00:01:15 +0000 |
---|---|---|
committer | Felix Kuehling <[email protected]> | 2004-12-17 00:01:15 +0000 |
commit | 0d39c4ebc9a5558c6b7514e33297e14445c5853f (patch) | |
tree | b245b279f41f8b4412e3fa199b5093ce735c6634 /src/mesa/drivers/dri/savage/savagetris.c | |
parent | c403bcb8a7be437976d5adce41189fff1e7f690f (diff) |
Added a TNL pipeline stage that normalizes texture coordinates as a
workaround for bad Savage hardware interpolation of big texture
coordinates.
Diffstat (limited to 'src/mesa/drivers/dri/savage/savagetris.c')
-rw-r--r-- | src/mesa/drivers/dri/savage/savagetris.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/savage/savagetris.c b/src/mesa/drivers/dri/savage/savagetris.c index e2fcd6c62bf..7ddb41c37bd 100644 --- a/src/mesa/drivers/dri/savage/savagetris.c +++ b/src/mesa/drivers/dri/savage/savagetris.c @@ -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 */ +}; |