summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix Kuehling <fxkuehl@gmx.de>2004-12-17 00:01:15 +0000
committerFelix Kuehling <fxkuehl@gmx.de>2004-12-17 00:01:15 +0000
commit0d39c4ebc9a5558c6b7514e33297e14445c5853f (patch)
treeb245b279f41f8b4412e3fa199b5093ce735c6634 /src
parentc403bcb8a7be437976d5adce41189fff1e7f690f (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')
-rw-r--r--src/mesa/drivers/dri/savage/savage_xmesa.c18
-rw-r--r--src/mesa/drivers/dri/savage/savagetris.c186
2 files changed, 203 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c
index 944262c3cf9..70827ea5595 100644
--- a/src/mesa/drivers/dri/savage/savage_xmesa.c
+++ b/src/mesa/drivers/dri/savage/savage_xmesa.c
@@ -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
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 */
+};