Added a fast path for emitting unclipped primitives directly to a
authorFelix Kuehling <fxkuehl@gmx.de>
Sun, 16 Jan 2005 01:28:26 +0000 (01:28 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Sun, 16 Jan 2005 01:28:26 +0000 (01:28 +0000)
vertex buffer. ELTS are not supported yet (missing functionality in
the DRM). You need at least Savage DRM version 2.1.3, which fixes a
bug that screwed up triangle fans and strips.

Moved the texture normalization stage to savagerender.c.

src/mesa/drivers/dri/savage/Makefile
src/mesa/drivers/dri/savage/savage_xmesa.c
src/mesa/drivers/dri/savage/savagerender.c [new file with mode: 0644]
src/mesa/drivers/dri/savage/savagestate.c
src/mesa/drivers/dri/savage/savagetris.c

index 181556318fbc4e7285dc885b9b9a54ade972079c..204c3b03cba2ff500309c2fcc73fa40639b1e825 100644 (file)
@@ -24,6 +24,7 @@ DRIVER_SOURCES = \
        savagestate.c \
        savagetex.c \
        savagetris.c \
+       savagerender.c \
        savageioctl.c \
        savagespan.c
 
index a1c5142d4ff448756465a1ef34f91ff0e69079a9..9a8e090ab5164a5946edad315a0fb56864753588 100644 (file)
@@ -110,6 +110,7 @@ static const char *const card_extensions[] =
 };
 
 extern const struct tnl_pipeline_stage _savage_texnorm_stage;
+extern const struct tnl_pipeline_stage _savage_render_stage;
 
 static const struct tnl_pipeline_stage *savage_pipeline[] = {
 
@@ -120,6 +121,7 @@ static const struct tnl_pipeline_stage *savage_pipeline[] = {
    &_tnl_texgen_stage,
    &_tnl_texture_transform_stage,
    &_savage_texnorm_stage,
+   &_savage_render_stage,
    &_tnl_render_stage,
    0,
 };
@@ -426,10 +428,10 @@ savageCreateContext( const __GLcontextModes *mesaVis,
    imesa->dmaVtxBuf.used = 0;
    imesa->dmaVtxBuf.flushed = 0;
 
-   imesa->clientVtxBuf.total = 16384;
+   imesa->clientVtxBuf.total = imesa->bufferSize / 4;
    imesa->clientVtxBuf.used = 0;
    imesa->clientVtxBuf.flushed = 0;
-   imesa->clientVtxBuf.buf = (u_int32_t *)malloc(16384*4);
+   imesa->clientVtxBuf.buf = (u_int32_t *)malloc(imesa->bufferSize);
 
    imesa->vtxBuf = &imesa->clientVtxBuf;
 
diff --git a/src/mesa/drivers/dri/savage/savagerender.c b/src/mesa/drivers/dri/savage/savagerender.c
new file mode 100644 (file)
index 0000000..50ec9ea
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2005  Felix Kuehling
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers.  Use strip/fan hardware primitives where possible.
+ * Simulate missing primitives with indexed vertices.
+ */
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+
+#include "tnl/t_context.h"
+
+#include "savagecontext.h"
+#include "savagetris.h"
+#include "savagestate.h"
+#include "savageioctl.h"
+
+/*
+ * Standard render tab for Savage4 and smooth shading on Savage3D
+ */
+#define HAVE_POINTS      0
+#define HAVE_LINES       0
+#define HAVE_LINE_STRIPS 0
+#define HAVE_TRIANGLES   1
+#define HAVE_TRI_STRIPS  1
+#define HAVE_TRI_STRIP_1 0
+#define HAVE_TRI_FANS    1
+#define HAVE_POLYGONS    0
+#define HAVE_QUADS       0
+#define HAVE_QUAD_STRIPS 0
+
+#define HAVE_ELTS        0     /* for now */
+
+#define LOCAL_VARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx) 
+#define INIT( prim ) do {                                              \
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);                       \
+   savageFlushVertices(imesa);                                         \
+   switch (prim) {                                                     \
+   case GL_TRIANGLES:     imesa->HwPrim = SAVAGE_PRIM_TRILIST; break;  \
+   case GL_TRIANGLE_STRIP: imesa->HwPrim = SAVAGE_PRIM_TRISTRIP; break;        \
+   case GL_TRIANGLE_FAN:   imesa->HwPrim = SAVAGE_PRIM_TRIFAN; break;  \
+   }                                                                   \
+} while (0)
+#define FLUSH()                savageFlushVertices(imesa)
+#define GET_CURRENT_VB_MAX_VERTS() \
+   ((imesa->bufferSize/4 - imesa->vtxBuf->used) / imesa->HwVertexSize)
+#define GET_SUBSEQUENT_VB_MAX_VERTS() \
+   (imesa->bufferSize/4 / imesa->HwVertexSize)
+
+#define ALLOC_VERTS( nr ) \
+       savageAllocVtxBuf( imesa, (nr) * imesa->HwVertexSize )
+#define EMIT_VERTS( ctx, j, nr, buf ) \
+       _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf )
+
+#define TAG(x) savage_##x
+#include "tnl_dd/t_dd_dmatmp.h"
+
+/*
+ * On Savage3D triangle fans and strips are broken with flat
+ * shading. With triangles it wants the color for flat shading in the
+ * first vertex! So we make another template instance which uses
+ * triangles only (with reordered vertices: SAVAGE_PRIM_TRILIST_201).
+ * The reordering is done by the DRM.
+ */
+#undef  HAVE_TRI_STRIPS
+#undef  HAVE_TRI_FANS
+#define HAVE_TRI_STRIPS        0
+#define HAVE_TRI_FANS  0
+
+#undef  INIT
+#define INIT( prim ) do {                                              \
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);                       \
+   savageFlushVertices(imesa);                                         \
+   imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;                            \
+} while(0)
+
+#undef  TAG
+#define TAG(x) savage_flat_##x##_s3d
+#include "tnl_dd/t_dd_dmatmp.h"
+
+
+/**********************************************************************/
+/*                          Render pipeline stage                     */
+/**********************************************************************/
+
+static GLboolean savage_run_render( GLcontext *ctx,
+                                   struct tnl_pipeline_stage *stage )
+{
+   savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb; 
+   tnl_render_func *tab;
+   GLboolean valid;
+   GLuint i;
+
+   if (imesa->savageScreen->chipset < S3_SAVAGE4 &&
+       (ctx->_TriangleCaps & DD_FLATSHADE)) {
+      tab = savage_flat_render_tab_verts_s3d;
+      valid = savage_flat_validate_render_s3d( ctx, VB );
+   } else {
+      tab = savage_render_tab_verts;
+      valid = savage_validate_render( ctx, VB );
+   }
+
+   /* Don't handle clipping or indexed vertices or vertex manipulations.
+    */
+   if (imesa->RenderIndex != 0 || !valid) {
+      return GL_TRUE;
+   }
+   
+   tnl->Driver.Render.Start( ctx );
+   /* Check RenderIndex again. The ptexHack is detected late in RenderStart.
+    * Also check for fallbacks detected late.
+    */
+   if (imesa->RenderIndex != 0 || imesa->Fallback != 0) {
+      return GL_TRUE;
+   }
+
+   /* setup for hardware culling */
+   imesa->raster_primitive = GL_TRIANGLES;
+   imesa->new_state |= SAVAGE_NEW_CULL;
+   savageDDUpdateHwState(ctx);
+
+   for (i = 0 ; i < VB->PrimitiveCount ; i++)
+   {
+      GLuint prim = VB->Primitive[i].mode;
+      GLuint start = VB->Primitive[i].start;
+      GLuint length = VB->Primitive[i].count;
+
+      if (length)
+        tab[prim & PRIM_MODE_MASK]( ctx, start, start+length, prim);
+   }
+
+   tnl->Driver.Render.Finish( ctx );
+
+   return GL_FALSE;            /* finished the pipe */
+}
+
+static void savage_check_render( GLcontext *ctx,
+                                struct tnl_pipeline_stage *stage )
+{
+   __DRIscreenPrivate *driScrnPriv =
+      SAVAGE_CONTEXT(ctx)->savageScreen->driScrnPriv;
+   stage->inputs = TNL_CONTEXT(ctx)->render_inputs;
+   /* This hack will go away when we depend on 2.2.x for ELTS. */
+   if (driScrnPriv->drmMinor <= 1 && driScrnPriv->drmPatch < 3) {
+      static GLboolean firstTime = GL_TRUE;
+      stage->active = GL_FALSE;
+      if (firstTime) {
+        fprintf (stderr,
+                 "*** Disabling fast path because your DRM version is buggy.\n"
+                 "*** You need at least Savage DRM version 2.1.3.\n");
+        firstTime = GL_FALSE;
+      }
+   }
+}
+
+static void dtr( struct tnl_pipeline_stage *stage )
+{
+   (void)stage;
+}
+
+const struct tnl_pipeline_stage _savage_render_stage = 
+{ 
+   "savage render",
+   (_DD_NEW_SEPARATE_SPECULAR |
+    _NEW_TEXTURE|
+    _NEW_FOG|
+    _NEW_RENDERMODE),          /* re-check (new inputs) */
+   0,                          /* re-run (always runs) */
+   GL_TRUE,                    /* active */
+   0, 0,                       /* inputs (set in check_render), outputs */
+   0, 0,                       /* changed_inputs, private */
+   dtr,                                /* destructor */
+   savage_check_render,                /* check - initially set to alloc data */
+   savage_run_render           /* run */
+};
+
+
+/**********************************************************************/
+/*         Pipeline stage for texture coordinate normalization        */
+/**********************************************************************/
+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)) ||
+         VB->TexCoordPtr[i]->size == 4)
+        /* Never try to normalize homogenous tex coords! */
+        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) {
+        /* take first texcoords as rough estimate of mean value */
+        GLfloat correctionS = -floor(in[0]+0.5);
+        GLfloat correctionT = -floor(in[1]+0.5);
+        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) {
+        /* take first texcoords as rough estimate of mean value */
+        GLfloat correctionS = -floor(in[0]+0.5);
+        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) {
+        /* take first texcoords as rough estimate of mean value */
+        GLfloat correctionT = -floor(in[1]+0.5);
+        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 */
+};
index b57fa39dd8d1167050ded7261de9da87c6f0cb43..2b512c11410c2deafd0e27dbe53874ed8383efd7 100644 (file)
@@ -825,7 +825,7 @@ static void savageUpdateCull( GLcontext *ctx )
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
     GLuint cullMode;
     if (ctx->Polygon.CullFlag &&
-       imesa->raster_primitive == GL_TRIANGLES &&
+       imesa->raster_primitive >= GL_TRIANGLES &&
        ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
        cullMode = imesa->LcsCullMode;
     else
index 382eccc82c8c5313203ba17d857bc34dd751273f..0092f3ea770fe4b763c1cbce3b8957346ceca572 100644 (file)
@@ -762,16 +762,6 @@ static void savageChooseRenderState(GLcontext *ctx)
 
       imesa->RenderIndex = index;
    }
-
-   if (imesa->savageScreen->chipset < S3_SAVAGE4 && (flags & DD_FLATSHADE)) {
-      if (imesa->HwPrim != SAVAGE_PRIM_TRILIST_201)
-        savageFlushVertices(imesa);
-      imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;
-   } else {
-      if (imesa->HwPrim != SAVAGE_PRIM_TRILIST)
-        savageFlushVertices(imesa);
-      imesa->HwPrim = SAVAGE_PRIM_TRILIST;
-   }
 }
 
 /**********************************************************************/
@@ -788,10 +778,22 @@ static void savageRunPipeline( GLcontext *ctx )
    if (imesa->new_state)
       savageDDUpdateHwState( ctx );
 
-   if (!imesa->Fallback && imesa->new_gl_state) {
+   if (!imesa->Fallback) {
       if (imesa->new_gl_state & _SAVAGE_NEW_RENDER_STATE)
         savageChooseRenderState( ctx );
 
+      /* choose the correct primitive type for tnl rendering */
+      if (imesa->savageScreen->chipset < S3_SAVAGE4 &&
+         (ctx->_TriangleCaps & DD_FLATSHADE)) {
+        if (imesa->HwPrim != SAVAGE_PRIM_TRILIST_201)
+           savageFlushVertices(imesa);
+        imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;
+      } else {
+        if (imesa->HwPrim != SAVAGE_PRIM_TRILIST)
+           savageFlushVertices(imesa);
+        imesa->HwPrim = SAVAGE_PRIM_TRILIST;
+      }
+
       imesa->new_gl_state = 0;
    }
 
@@ -1288,162 +1290,3 @@ 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)) ||
-         VB->TexCoordPtr[i]->size == 4)
-        /* Never try to normalize homogenous tex coords! */
-        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) {
-        /* take first texcoords as rough estimate of mean value */
-        GLfloat correctionS = -floor(in[0]+0.5);
-        GLfloat correctionT = -floor(in[1]+0.5);
-        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) {
-        /* take first texcoords as rough estimate of mean value */
-        GLfloat correctionS = -floor(in[0]+0.5);
-        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) {
-        /* take first texcoords as rough estimate of mean value */
-        GLfloat correctionT = -floor(in[1]+0.5);
-        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 */
-};