Added a TNL pipeline stage that normalizes texture coordinates as a
authorFelix Kuehling <fxkuehl@gmx.de>
Fri, 17 Dec 2004 00:01:15 +0000 (00:01 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Fri, 17 Dec 2004 00:01:15 +0000 (00:01 +0000)
workaround for bad Savage hardware interpolation of big texture
coordinates.

src/mesa/drivers/dri/savage/savage_xmesa.c
src/mesa/drivers/dri/savage/savagetris.c

index 944262c..70827ea 100644 (file)
@@ -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
index e2fcd6c..7ddb41c 100644 (file)
@@ -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 */
+};