Removed knowledge of swrast Clear/Bitmap/Accum/Draw/Read/CopyPixels
[mesa.git] / src / mesa / drivers / glide / fxdd.c
index 4768e1a2339ab0615cb532c70551599b59c0bb4e..175077833c968e866f3e25718dee5f396c0e2a4a 100644 (file)
@@ -1,4 +1,3 @@
-/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */
 
 /*
  * Mesa 3-D graphics library
 #if defined(FX)
 
 #include "image.h"
-#include "types.h"
+#include "mtypes.h"
 #include "fxdrv.h"
 #include "enums.h"
 #include "extensions.h"
 #include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "array_cache/acache.h"
+
+#include "tnl/t_pipeline.h"
+
+
+float gl_ubyte_to_float_255_color_tab[256];
 
 /* These lookup table are used to extract RGB values in [0,255] from
  * 16-bit pixel values.
@@ -120,45 +127,26 @@ static void fxDDBufferSize(GLcontext *ctx, GLuint *width, GLuint *height)
 }
 
 
-/* Set current drawing color */
-static void fxDDSetColor(GLcontext *ctx, GLubyte red, GLubyte green,
-                         GLubyte blue, GLubyte alpha )
-{
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-  GLubyte col[4];
-  ASSIGN_4V( col, red, green, blue, alpha );
-  
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
-  }
-
-  fxMesa->color=FXCOLOR4(col);
-}
-
-
 /* Implements glClearColor() */
-static void fxDDClearColor(GLcontext *ctx, GLubyte red, GLubyte green,
-                           GLubyte blue, GLubyte alpha )
+static void fxDDClearColor(GLcontext *ctx, const GLchan color[4])
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GLubyte col[4];
 
-
-
-  ASSIGN_4V( col, red, green, blue, 255 );
-
   if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
+    fprintf(stderr,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",
+            color[0], color[1], color[2], color[3]);
   }
-  fxMesa->clearC=FXCOLOR4( col );
-  fxMesa->clearA=alpha;
+
+  ASSIGN_4V( col, color[0], color[1], color[2], 255 );
+  fxMesa->clearC = FXCOLOR4( col );
+  fxMesa->clearA = color[3];
 }
 
 
 /* Clear the color and/or depth buffers */
-static GLbitfield fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                            GLint x, GLint y, GLint width, GLint height )
+static void fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+                     GLint x, GLint y, GLint width, GLint height )
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
@@ -267,7 +255,10 @@ static GLbitfield fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
       ;
   }
 
-  return softwareMask;
+  /* Clear any remaining buffers:
+   */
+  if (softwareMask) 
+     _swrast_Clear( ctx, softwareMask, all, x, y, width, height );
 }
 
 
@@ -324,26 +315,11 @@ static void fxDDSetReadBuffer(GLcontext *ctx, GLframebuffer *buffer,
 }
 
 
-#ifdef XF86DRI
-/* test if window coord (px,py) is visible */
-static GLboolean inClipRects(fxMesaContext fxMesa, int px, int py)
-{
-  int i;
-  for (i=0; i<fxMesa->numClipRects; i++) {
-    if ((px>=fxMesa->pClipRects[i].x1) && 
-       (px<fxMesa->pClipRects[i].x2) &&
-       (py>=fxMesa->pClipRects[i].y1) && 
-       (py<fxMesa->pClipRects[i].y2)) return GL_TRUE;
-  }
-  return GL_FALSE;
-}
-#endif
-
 
-static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
-                                GLsizei width, GLsizei height,
-                                const struct gl_pixelstore_attrib *unpack,
-                                const GLubyte *bitmap)
+static void fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
+                          GLsizei width, GLsizei height,
+                          const struct gl_pixelstore_attrib *unpack,
+                          const GLubyte *bitmap)
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GrLfbInfo_t info;
@@ -352,22 +328,28 @@ static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
   struct gl_pixelstore_attrib scissoredUnpack;
 
   /* check if there's any raster operations enabled which we can't handle */
-  if (ctx->RasterMask & (ALPHATEST_BIT |
-                         BLEND_BIT |
-                         DEPTH_BIT |
-                         FOG_BIT |
-                         LOGIC_OP_BIT |
-                         SCISSOR_BIT |
-                         STENCIL_BIT |
-                         MASKING_BIT |
-                         ALPHABUF_BIT |
-                         MULTI_DRAW_BIT))
-    return GL_FALSE;
+  if (ctx->Color.AlphaEnabled ||
+      ctx->Color.BlendEnabled ||
+      ctx->Depth.Test ||
+      ctx->Fog.Enabled ||
+      ctx->Color.ColorLogicOpEnabled ||
+      ctx->Stencil.Enabled ||
+      ctx->Scissor.Enabled ||
+      (  ctx->DrawBuffer->UseSoftwareAlphaBuffers &&
+         ctx->Color.ColorMask[ACOMP]) ||
+      ctx->Color.MultiDrawBuffer) 
+  {
+     _swrast_Bitmap( ctx, px, py, width, height, unpack, bitmap );
+     return;
+  }
+
 
   if (ctx->Scissor.Enabled) {
     /* This is a bit tricky, but by carefully adjusting the px, py,
      * width, height, skipPixels and skipRows values we can do
      * scissoring without special code in the rendering loop.
+     *
+     * KW: This code is never reached, see the test above.
      */
 
     /* we'll construct a new pixelstore struct */
@@ -398,8 +380,8 @@ static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
     }
 
     if (width <= 0 || height <= 0)
-      return GL_TRUE;  /* totally scissored away */
-  }  
+       return;
+  }
   else {
     finalUnpack = unpack;
   }
@@ -432,28 +414,18 @@ static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
 #ifndef FX_SILENT
     fprintf(stderr,"fx Driver: error locking the linear frame buffer\n");
 #endif
-    return GL_TRUE;
+    return;
   }
 
-#ifdef XF86DRI
-#define INSIDE(c, x, y) inClipRects((c), (x), (y))
-#else
-#define INSIDE(c, x, y) (1)
-#endif
-
   {
-    const GLint winX = fxMesa->x_offset;
-    const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
+    const GLint winX = 0;
+    const GLint winY = fxMesa->height - 1;
     /* The dest stride depends on the hardware and whether we're drawing
      * to the front or back buffer.  This compile-time test seems to do
      * the job for now.
      */
-#ifdef XF86DRI
-    const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
-                          ? (fxMesa->screen_width) : (info.strideInBytes / 2);
-#else
     const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
-#endif
+
     GLint row;
     /* compute dest address of bottom-left pixel in bitmap */
     GLushort *dst = (GLushort *) info.lfbPtr
@@ -469,8 +441,7 @@ static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
         GLint col;
         for (col=0; col<width; col++) {
           if (*src & mask) {
-            if (INSIDE(fxMesa, winX + px + col, winY - py - row))
-              dst[col] = color;
+           dst[col] = color;
           }
           if (mask == 128U) {
             src++;
@@ -489,8 +460,7 @@ static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
         GLint col;
         for (col=0; col<width; col++) {
           if (*src & mask) {
-            if (INSIDE(fxMesa, winX + px + col, winY - py - row))
-              dst[col] = color;
+           dst[col] = color;
           }
           if (mask == 1U) {
             src++;
@@ -507,129 +477,122 @@ static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py,
     }
   }
 
-#undef INSIDE
-
   FX_grLfbUnlock(GR_LFB_WRITE_ONLY,fxMesa->currentFB);
-  return GL_TRUE;
 }
 
 
-static GLboolean fxDDReadPixels( GLcontext *ctx, GLint x, GLint y,
-                                 GLsizei width, GLsizei height,
-                                 GLenum format, GLenum type,
-                                 const struct gl_pixelstore_attrib *packing,
-                                 GLvoid *dstImage )
+static void fxDDReadPixels( GLcontext *ctx, GLint x, GLint y,
+                           GLsizei width, GLsizei height,
+                           GLenum format, GLenum type,
+                           const struct gl_pixelstore_attrib *packing,
+                           GLvoid *dstImage )
 {
-  if (ctx->ImageTransferState) {
-    return GL_FALSE;  /* can't do this */
-  }
-  else {
-    fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-    GrLfbInfo_t info;
-    GLboolean result = GL_FALSE;
-
-    BEGIN_BOARD_LOCK();
-    if (grLfbLock(GR_LFB_READ_ONLY,
-                  fxMesa->currentFB,
-                  GR_LFBWRITEMODE_ANY,
-                  GR_ORIGIN_UPPER_LEFT,
-                  FXFALSE,
-                  &info)) {
-      const GLint winX = fxMesa->x_offset;
-      const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
-#ifdef XF86DRI
-      const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
-                          ? (fxMesa->screen_width) : (info.strideInBytes / 2);
-#else
-      const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
-#endif
-      const GLushort *src = (const GLushort *) info.lfbPtr
-                          + (winY - y) * srcStride + (winX + x);
-      GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
-                                         width, height, format, type, 0, 0, 0);
-      GLint dstStride = _mesa_image_row_stride(packing, width, format, type);
-
-      if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
-        /* convert 5R6G5B into 8R8G8B */
-        GLint row, col;
-        const GLint halfWidth = width >> 1;
-        const GLint extraPixel = (width & 1);
-        for (row = 0; row < height; row++) {
-          GLubyte *d = dst;
-          for (col = 0; col < halfWidth; col++) {
-            const GLuint pixel = ((const GLuint *) src)[col];
-            const GLint pixel0 = pixel & 0xffff;
-            const GLint pixel1 = pixel >> 16;
-            *d++ = FX_PixelToR[pixel0];
-            *d++ = FX_PixelToG[pixel0];
-            *d++ = FX_PixelToB[pixel0];
-            *d++ = FX_PixelToR[pixel1];
-            *d++ = FX_PixelToG[pixel1];
-            *d++ = FX_PixelToB[pixel1];
-          }
-          if (extraPixel) {
-            GLushort pixel = src[width-1];
-            *d++ = FX_PixelToR[pixel];
-            *d++ = FX_PixelToG[pixel];
-            *d++ = FX_PixelToB[pixel];
-          }
-          dst += dstStride;
-          src -= srcStride;
-        }
-        result = GL_TRUE;
-      }
-      else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
-        /* convert 5R6G5B into 8R8G8B8A */
-        GLint row, col;
-        const GLint halfWidth = width >> 1;
-        const GLint extraPixel = (width & 1);
-        for (row = 0; row < height; row++) {
-          GLubyte *d = dst;
-          for (col = 0; col < halfWidth; col++) {
-            const GLuint pixel = ((const GLuint *) src)[col];
-            const GLint pixel0 = pixel & 0xffff;
-            const GLint pixel1 = pixel >> 16;
-            *d++ = FX_PixelToR[pixel0];
-            *d++ = FX_PixelToG[pixel0];
-            *d++ = FX_PixelToB[pixel0];
-            *d++ = 255;
-            *d++ = FX_PixelToR[pixel1];
-            *d++ = FX_PixelToG[pixel1];
-            *d++ = FX_PixelToB[pixel1];
-            *d++ = 255;
-          }
-          if (extraPixel) {
-            const GLushort pixel = src[width-1];
-            *d++ = FX_PixelToR[pixel];
-            *d++ = FX_PixelToG[pixel];
-            *d++ = FX_PixelToB[pixel];
-            *d++ = 255;
-          }
-          dst += dstStride;
-          src -= srcStride;
-        }
-        result = GL_TRUE;
-      }
-      else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
-        /* directly memcpy 5R6G5B pixels into client's buffer */
-        const GLint widthInBytes = width * 2;
-        GLint row;
-        for (row = 0; row < height; row++) {
-          MEMCPY(dst, src, widthInBytes);
-          dst += dstStride;
-          src -= srcStride;
-        }
-        result = GL_TRUE;
-      }
-      else {
-        result = GL_FALSE;
+   if (ctx->_ImageTransferState) {
+      _swrast_ReadPixels( ctx, x, y, width, height, format, type,
+                         packing, dstImage );
+      return;  
+   }
+   else {
+      fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+      GrLfbInfo_t info;
+
+      BEGIN_BOARD_LOCK();
+      if (grLfbLock(GR_LFB_READ_ONLY,
+                   fxMesa->currentFB,
+                   GR_LFBWRITEMODE_ANY,
+                   GR_ORIGIN_UPPER_LEFT,
+                   FXFALSE,
+                   &info)) {
+        const GLint winX = 0;
+        const GLint winY = fxMesa->height - 1;
+        const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
+        const GLushort *src = (const GLushort *) info.lfbPtr
+           + (winY - y) * srcStride + (winX + x);
+        GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
+                                                       width, height, format, type, 0, 0, 0);
+        GLint dstStride = _mesa_image_row_stride(packing, width, format, type);
+
+        if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+           /* convert 5R6G5B into 8R8G8B */
+           GLint row, col;
+           const GLint halfWidth = width >> 1;
+           const GLint extraPixel = (width & 1);
+           for (row = 0; row < height; row++) {
+              GLubyte *d = dst;
+              for (col = 0; col < halfWidth; col++) {
+                 const GLuint pixel = ((const GLuint *) src)[col];
+                 const GLint pixel0 = pixel & 0xffff;
+                 const GLint pixel1 = pixel >> 16;
+                 *d++ = FX_PixelToR[pixel0];
+                 *d++ = FX_PixelToG[pixel0];
+                 *d++ = FX_PixelToB[pixel0];
+                 *d++ = FX_PixelToR[pixel1];
+                 *d++ = FX_PixelToG[pixel1];
+                 *d++ = FX_PixelToB[pixel1];
+              }
+              if (extraPixel) {
+                 GLushort pixel = src[width-1];
+                 *d++ = FX_PixelToR[pixel];
+                 *d++ = FX_PixelToG[pixel];
+                 *d++ = FX_PixelToB[pixel];
+              }
+              dst += dstStride;
+              src -= srcStride;
+           }
+        }
+        else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+           /* convert 5R6G5B into 8R8G8B8A */
+           GLint row, col;
+           const GLint halfWidth = width >> 1;
+           const GLint extraPixel = (width & 1);
+           for (row = 0; row < height; row++) {
+              GLubyte *d = dst;
+              for (col = 0; col < halfWidth; col++) {
+                 const GLuint pixel = ((const GLuint *) src)[col];
+                 const GLint pixel0 = pixel & 0xffff;
+                 const GLint pixel1 = pixel >> 16;
+                 *d++ = FX_PixelToR[pixel0];
+                 *d++ = FX_PixelToG[pixel0];
+                 *d++ = FX_PixelToB[pixel0];
+                 *d++ = 255;
+                 *d++ = FX_PixelToR[pixel1];
+                 *d++ = FX_PixelToG[pixel1];
+                 *d++ = FX_PixelToB[pixel1];
+                 *d++ = 255;
+              }
+              if (extraPixel) {
+                 const GLushort pixel = src[width-1];
+                 *d++ = FX_PixelToR[pixel];
+                 *d++ = FX_PixelToG[pixel];
+                 *d++ = FX_PixelToB[pixel];
+                 *d++ = 255;
+              }
+              dst += dstStride;
+              src -= srcStride;
+           }
+        }
+        else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
+           /* directly memcpy 5R6G5B pixels into client's buffer */
+           const GLint widthInBytes = width * 2;
+           GLint row;
+           for (row = 0; row < height; row++) {
+              MEMCPY(dst, src, widthInBytes);
+              dst += dstStride;
+              src -= srcStride;
+           }
+        }
+        else {
+           grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+           END_BOARD_LOCK();
+           _swrast_ReadPixels( ctx, x, y, width, height, format, type,
+                               packing, dstImage );
+           return;
+        }
+
+        grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
       }
-
-      grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
-    }
-    END_BOARD_LOCK();
-    return result;
-  }
+      END_BOARD_LOCK();
+   }
 }
 
 
@@ -640,25 +603,8 @@ static void fxDDFinish(GLcontext *ctx)
 }
 
 
-static GLint fxDDGetParameteri(const GLcontext *ctx, GLint param)
-{
-  switch(param) {
-  case DD_HAVE_HARDWARE_FOG:
-    return 1;
-  default:
-    fprintf(stderr,"fx Driver: internal error in fxDDGetParameteri(): %x\n", (int) param);
-    fxCloseHardware();
-    exit(-1);
-    return 0;
-  }
-}
 
 
-void fxDDSetNearFar(GLcontext *ctx, GLfloat n, GLfloat f)
-{
-   FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
-   ctx->Driver.RenderStart = fxSetupFXUnits;
-}
 
 /* KW: Put the word Mesa in the render string because quakeworld
  * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
@@ -666,46 +612,13 @@ void fxDDSetNearFar(GLcontext *ctx, GLfloat n, GLfloat f)
  */
 static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name)
 {
-#if defined(GLX_DIRECT_RENDERING)
-  /* Building for DRI driver */
-  switch (name) {
-    case GL_RENDERER:
-      {
-        static char buffer[100];
-        char hardware[100];
-        strcpy(hardware, grGetString(GR_HARDWARE));
-        if (strcmp(hardware, "Voodoo3 (tm)") == 0)
-          strcpy(hardware, "Voodoo3");
-        else if (strcmp(hardware, "Voodoo Banshee (tm)") == 0)
-          strcpy(hardware, "VoodooBanshee");
-        else {
-          /* unexpected result: replace spaces with hyphens */
-          int i;
-          for (i = 0; hardware[i]; i++) {
-            if (hardware[i] == ' ' || hardware[i] == '\t')
-              hardware[i] = '-';
-          }
-        }
-        /* now make the GL_RENDERER string */
-        sprintf(buffer, "Mesa DRI %s 20000510", hardware);
-        return buffer;
-      }
-    case GL_VENDOR:
-      return "Precision Insight, Inc.";
-    default:
-      return NULL;
-  }
-
-#else
-
-  /* Building for Voodoo1/2 stand-alone Mesa */
   switch (name) {
     case GL_RENDERER:
       {
         static char buf[80];
 
         if (glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
-          GrVoodooConfig_t *vc = 
+          GrVoodooConfig_t *vc =
             &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig;
 
           sprintf(buf,
@@ -719,7 +632,7 @@ static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name)
                   (vc->sliDetect ? "SLI" : "NOSLI"));
         }
         else if (glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) {
-          GrSst96Config_t *sc = 
+          GrSst96Config_t *sc =
             &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config;
 
           sprintf(buf,
@@ -738,23 +651,49 @@ static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name)
     default:
       return NULL;
   }
-#endif
 }
 
+static const struct gl_pipeline_stage *fx_pipeline[] = {
+   &_tnl_update_material_stage, /* TODO: Add the fastpath here */
+   &_tnl_vertex_transform_stage, 
+   &_tnl_normal_transform_stage, 
+   &_tnl_lighting_stage,       
+   &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage */
+   &_tnl_texgen_stage, 
+   &_tnl_texture_transform_stage, 
+   &_tnl_point_attenuation_stage, 
+   &_tnl_render_stage,         
+   0,
+};
+
+
+
 
 int fxDDInitFxMesaContext( fxMesaContext fxMesa )
 {
-  
+   int i;
+   static int firsttime = 1;
+
+   for (i = 0 ; i < 256 ; i++) {
+      gl_ubyte_to_float_255_color_tab[i] = (float) i;
+   }
+
+   if (firsttime) {
+      fxDDSetupInit();
+      fxDDTrifuncInit();
+      firsttime = 0;
+   }
+
    FX_setupGrVertexLayout();
-   
-   if (getenv("FX_EMULATE_SINGLE_TMU")) 
+
+   if (getenv("FX_EMULATE_SINGLE_TMU"))
       fxMesa->haveTwoTMUs = GL_FALSE;
-      
+
    fxMesa->emulateTwoTMUs = fxMesa->haveTwoTMUs;
-   
-   if (!getenv("FX_DONT_FAKE_MULTITEX")) 
+
+   if (!getenv("FX_DONT_FAKE_MULTITEX"))
       fxMesa->emulateTwoTMUs = GL_TRUE;
-      
+
    if(getenv("FX_GLIDE_SWAPINTERVAL"))
       fxMesa->swapInterval=atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
    else
@@ -764,7 +703,7 @@ int fxDDInitFxMesaContext( fxMesaContext fxMesa )
       fxMesa->maxPendingSwapBuffers=atoi(getenv("MESA_FX_SWAP_PENDING"));
    else
       fxMesa->maxPendingSwapBuffers=2;
-   
+
    if(getenv("MESA_FX_INFO"))
       fxMesa->verbose=GL_TRUE;
    else
@@ -807,12 +746,10 @@ int fxDDInitFxMesaContext( fxMesaContext fxMesa )
       fxMesa->currentFB=GR_BUFFER_FRONTBUFFER;
       FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
    }
-  
-   fxMesa->state       = NULL;
-   fxMesa->fogTable    = NULL;
-  
-   fxMesa->state       = malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE));
-   fxMesa->fogTable    = malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES)*sizeof(GrFog_t));
+    
+   fxMesa->state = malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE));
+   fxMesa->fogTable = malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES) * 
+                            sizeof(GrFog_t));
   
    if (!fxMesa->state || !fxMesa->fogTable) {
       if (fxMesa->state) free(fxMesa->state);
@@ -822,7 +759,7 @@ int fxDDInitFxMesaContext( fxMesaContext fxMesa )
 
    if(fxMesa->haveZBuffer)
       FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
-    
+
 #if (!FXMESA_USE_ARGB)
    FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); /* Not every Glide has this */
 #endif
@@ -832,34 +769,38 @@ int fxDDInitFxMesaContext( fxMesaContext fxMesa )
    fxMesa->glCtx->Const.MaxTextureSize=256;
    fxMesa->glCtx->Const.MaxTextureUnits=fxMesa->emulateTwoTMUs ? 2 : 1;
    fxMesa->new_state = _NEW_ALL;
-  
-   fxDDSetupInit();
-   fxDDClipInit();
-   fxDDTrifuncInit();
-   fxDDFastPathInit();
 
-   fxSetupDDPointers(fxMesa->glCtx);
-   fxDDRenderInit(fxMesa->glCtx);
-   fxDDInitExtensions(fxMesa->glCtx);  
+   /* Initialize the software rasterizer and helper modules.
+    */
+   _swrast_CreateContext( fxMesa->glCtx );
+   _ac_CreateContext( fxMesa->glCtx );
+   _tnl_CreateContext( fxMesa->glCtx );
+   _swsetup_CreateContext( fxMesa->glCtx );
 
-   fxDDSetNearFar(fxMesa->glCtx,1.0,100.0);
-  
-   FX_grGlideGetState((GrState*)fxMesa->state);
+   _tnl_destroy_pipeline( fxMesa->glCtx );
+   _tnl_install_pipeline( fxMesa->glCtx, fx_pipeline );
+   
+   fxAllocVB( fxMesa->glCtx );
+
+   fxSetupDDPointers(fxMesa->glCtx);
 
-   /* XXX Fix me: callback not registered when main VB is created.
+   /* Tell the software rasterizer to use pixel fog always.
     */
-   if (fxMesa->glCtx->VB) 
-      fxDDRegisterVB( fxMesa->glCtx->VB );
-  
-   /* XXX Fix me too: need to have the 'struct dd' prepared prior to
-    * creating the context... The below is broken if you try to insert
-    * new stages.  
+   _swrast_allow_vertex_fog( fxMesa->glCtx, GL_FALSE );
+   _swrast_allow_pixel_fog( fxMesa->glCtx, GL_TRUE );
+
+   /* Tell tnl not to calculate or use vertex fog factors.  (Needed to
+    * tell render stage not to clip fog coords).
     */
-   if (fxMesa->glCtx->NrPipelineStages)
-      fxMesa->glCtx->NrPipelineStages = fxDDRegisterPipelineStages( 
-        fxMesa->glCtx->PipelineStage,
-        fxMesa->glCtx->PipelineStage,
-        fxMesa->glCtx->NrPipelineStages);
+/*     _tnl_calculate_vertex_fog( fxMesa->glCtx, GL_FALSE ); */
+
+   fxDDInitExtensions(fxMesa->glCtx);  
+
+#ifdef FXVTXFMT
+   fxDDInitVtxfmt(fxMesa->glCtx);
+#endif
+
+   FX_grGlideGetState((GrState*)fxMesa->state);
 
    /* Run the config file */
    _mesa_context_initialize( fxMesa->glCtx );
@@ -867,14 +808,24 @@ int fxDDInitFxMesaContext( fxMesaContext fxMesa )
    return 1;
 }
 
-
-#if 0
-/* Example extension function */
-static void fxFooBarEXT(GLint i)
+/* Undo the above.
+ */
+void fxDDDestroyFxMesaContext( fxMesaContext fxMesa )
 {
-   printf("You called glFooBarEXT(%d)\n", i);
+   _swsetup_DestroyContext( fxMesa->glCtx );
+   _tnl_DestroyContext( fxMesa->glCtx );
+   _ac_DestroyContext( fxMesa->glCtx );
+   _swrast_DestroyContext( fxMesa->glCtx );
+
+   if (fxMesa->state)  
+      free(fxMesa->state);
+   if (fxMesa->fogTable)
+      free(fxMesa->fogTable);
+   fxTMClose(fxMesa);
+   fxFreeVB(fxMesa->glCtx);
 }
-#endif
+
+
 
 
 void fxDDInitExtensions( GLcontext *ctx )
@@ -887,33 +838,16 @@ void fxDDInitExtensions( GLcontext *ctx )
    gl_extensions_disable(ctx, "GL_EXT_blend_color");
    gl_extensions_disable(ctx, "GL_EXT_fog_coord");
 
+   if (1)
+      gl_extensions_disable(ctx, "GL_EXT_point_parameters"); 
+
    gl_extensions_add(ctx, GL_TRUE, "3DFX_set_global_palette", 0);
-   
+
    if (!fxMesa->haveTwoTMUs)
       gl_extensions_disable(ctx, "GL_EXT_texture_env_add");
-   
-   if (!fxMesa->emulateTwoTMUs) 
-      gl_extensions_disable(ctx, "GL_ARB_multitexture");
 
-
-   /* Example of hooking in an extension function.
-    * For DRI-based drivers, also see __driRegisterExtensions in the
-    * tdfx_xmesa.c file.
-    */
-#if 0
-   {
-     void **dispatchTable = (void **) ctx->Exec;
-     const int _gloffset_FooBarEXT = 555;  /* just an example number! */
-     const int tabSize = _glapi_get_dispatch_table_size();
-     assert(_gloffset_FooBarEXT < tabSize);
-     dispatchTable[_gloffset_FooBarEXT] = (void *) fxFooBarEXT;
-     /* XXX You would also need to hook into the display list dispatch
-      * table.  Really, the implementation of extensions might as well
-      * be in the core of Mesa since core Mesa and the device driver
-      * is one big shared lib.
-      */
-  }
-#endif
+   if (!fxMesa->emulateTwoTMUs)
+      gl_extensions_disable(ctx, "GL_ARB_multitexture");
 }
 
 
@@ -921,7 +855,7 @@ void fxDDInitExtensions( GLcontext *ctx )
 /************************************************************************/
 /************************************************************************/
 
-/* Check if the hardware supports the current context 
+/* Check if the hardware supports the current context
  *
  * Performs similar work to fxDDChooseRenderState() - should be merged.
  */
@@ -929,48 +863,49 @@ static GLboolean fxIsInHardware(GLcontext *ctx)
 {
    fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
 
-  if (!ctx->Hint.AllowDrawMem)
-     return GL_TRUE;           /* you'll take it and like it */
-
-  if((ctx->RasterMask & (STENCIL_BIT | MULTI_DRAW_BIT)) ||
-     ((ctx->Color.BlendEnabled) && (ctx->Color.BlendEquation!=GL_FUNC_ADD_EXT)) ||
-     ((ctx->Color.ColorLogicOpEnabled) && (ctx->Color.LogicOp!=GL_COPY)) ||
-     (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) ||
-     (!((ctx->Color.ColorMask[RCOMP]==ctx->Color.ColorMask[GCOMP]) &&
-        (ctx->Color.ColorMask[GCOMP]==ctx->Color.ColorMask[BCOMP]) &&
-        (ctx->Color.ColorMask[ACOMP]==ctx->Color.ColorMask[ACOMP])))
-     )
+   if (ctx->RenderMode != GL_RENDER)
+     return GL_FALSE;
+
+  if (ctx->Stencil.Enabled ||
+      ctx->Color.MultiDrawBuffer ||
+      ((ctx->Color.BlendEnabled) && (ctx->Color.BlendEquation!=GL_FUNC_ADD_EXT)) ||
+      ((ctx->Color.ColorLogicOpEnabled) && (ctx->Color.LogicOp!=GL_COPY)) ||
+      (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) ||
+      (!((ctx->Color.ColorMask[RCOMP]==ctx->Color.ColorMask[GCOMP]) &&
+        (ctx->Color.ColorMask[GCOMP]==ctx->Color.ColorMask[BCOMP]) &&
+        (ctx->Color.ColorMask[ACOMP]==ctx->Color.ColorMask[ACOMP])))
+    )
   {
      return GL_FALSE;
   }
   /* Unsupported texture/multitexture cases */
 
   if(fxMesa->emulateTwoTMUs) {
-    if((ctx->Enabled & (TEXTURE0_3D | TEXTURE1_3D)) ||
+    if((ctx->_Enabled & (TEXTURE0_3D | TEXTURE1_3D)) ||
        /* Not very well written ... */
-       ((ctx->Enabled & (TEXTURE0_1D | TEXTURE1_1D)) && 
-        ((ctx->Enabled & (TEXTURE0_2D | TEXTURE1_2D))!=(TEXTURE0_2D | TEXTURE1_2D)))
+       ((ctx->_Enabled & (TEXTURE0_1D | TEXTURE1_1D)) &&
+        ((ctx->_Enabled & (TEXTURE0_2D | TEXTURE1_2D))!=(TEXTURE0_2D | TEXTURE1_2D)))
        ) {
       return GL_FALSE;
     }
 
-    if (ctx->Texture.ReallyEnabled & TEXTURE0_2D) {
+    if (ctx->Texture._ReallyEnabled & TEXTURE0_2D) {
       if (ctx->Texture.Unit[0].EnvMode == GL_BLEND &&
-         (ctx->Texture.ReallyEnabled & TEXTURE1_2D ||
+         (ctx->Texture._ReallyEnabled & TEXTURE1_2D ||
           ctx->Texture.Unit[0].EnvColor[0] != 0 ||
           ctx->Texture.Unit[0].EnvColor[1] != 0 ||
           ctx->Texture.Unit[0].EnvColor[2] != 0 ||
           ctx->Texture.Unit[0].EnvColor[3] != 1)) {
         return GL_FALSE;
       }
-      if (ctx->Texture.Unit[0].Current->Image[0]->Border > 0)
+      if (ctx->Texture.Unit[0]._Current->Image[0]->Border > 0)
         return GL_FALSE;
     }
 
-    if (ctx->Texture.ReallyEnabled & TEXTURE1_2D) {
+    if (ctx->Texture._ReallyEnabled & TEXTURE1_2D) {
       if (ctx->Texture.Unit[1].EnvMode == GL_BLEND)
         return GL_FALSE;
-      if (ctx->Texture.Unit[0].Current->Image[0]->Border > 0)
+      if (ctx->Texture.Unit[0]._Current->Image[0]->Border > 0)
         return GL_FALSE;
     }
 
@@ -982,8 +917,8 @@ static GLboolean fxIsInHardware(GLcontext *ctx)
     /* KW: This was wrong (I think) and I changed it... which doesn't mean
      * it is now correct...
      */
-    if((ctx->Enabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) &&
-       (ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)))
+    if((ctx->_Enabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) &&
+       (ctx->_Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)))
     {
        /* Can't use multipass to blend a multitextured triangle - fall
        * back to software.
@@ -991,7 +926,7 @@ static GLboolean fxIsInHardware(GLcontext *ctx)
       if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled) {
          return GL_FALSE;
       }
-         
+       
        if ((ctx->Texture.Unit[0].EnvMode!=ctx->Texture.Unit[1].EnvMode) &&
           (ctx->Texture.Unit[0].EnvMode!=GL_MODULATE) &&
           (ctx->Texture.Unit[0].EnvMode!=GL_REPLACE)) /* q2, seems ok... */
@@ -1002,16 +937,16 @@ static GLboolean fxIsInHardware(GLcontext *ctx)
        }
     }
   } else {
-    if((ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) ||
+    if((ctx->_Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) ||
        /* Not very well written ... */
-       ((ctx->Enabled & TEXTURE0_1D) && 
-        (!(ctx->Enabled & TEXTURE0_2D)))
+       ((ctx->_Enabled & TEXTURE0_1D) &&
+        (!(ctx->_Enabled & TEXTURE0_2D)))
        ) {
       return GL_FALSE;
     }
 
-    
-    if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) &&
+
+    if((ctx->Texture._ReallyEnabled & TEXTURE0_2D) &&
        (ctx->Texture.Unit[0].EnvMode==GL_BLEND)) {
       return GL_FALSE;
     }
@@ -1020,145 +955,182 @@ static GLboolean fxIsInHardware(GLcontext *ctx)
   return GL_TRUE;
 }
 
+static void update_texture_scales( GLcontext *ctx )
+{
+   fxMesaContext fxMesa = FX_CONTEXT(ctx);
+   struct gl_texture_unit *t0 = &ctx->Texture.Unit[fxMesa->tmu_source[0]];
+   struct gl_texture_unit *t1 = &ctx->Texture.Unit[fxMesa->tmu_source[1]];
+     
+   if (t0 && t0->_Current && FX_TEXTURE_DATA(t0)) {
+      fxMesa->s0scale = FX_TEXTURE_DATA(t0)->sScale;
+      fxMesa->t0scale = FX_TEXTURE_DATA(t0)->tScale;
+      fxMesa->inv_s0scale = 1.0 / fxMesa->s0scale;
+      fxMesa->inv_t0scale = 1.0 / fxMesa->t0scale;
+   }
+   
+   if (t1 && t1->_Current && FX_TEXTURE_DATA(t1)) {
+      fxMesa->s1scale = FX_TEXTURE_DATA(t1)->sScale;
+      fxMesa->t1scale = FX_TEXTURE_DATA(t1)->tScale;
+      fxMesa->inv_s1scale = 1.0 / fxMesa->s1scale;
+      fxMesa->inv_t1scale = 1.0 / fxMesa->t1scale;
+   }
+}
 
-static void fxDDUpdateDDPointers(GLcontext *ctx)
+static void fxDDUpdateDDPointers(GLcontext *ctx, GLuint new_state)
 {
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-  GLuint new_state = ctx->NewState;
+   fxMesaContext fxMesa = FX_CONTEXT(ctx);
 
-  if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_STATE)) 
-    fprintf(stderr,"fxmesa: fxDDUpdateDDPointers(...)\n");
+   _swrast_InvalidateState( ctx, new_state );
+   _ac_InvalidateState( ctx, new_state );
+   _tnl_InvalidateState( ctx, new_state );
+   _swsetup_InvalidateState( ctx, new_state );
 
-  if (new_state & _FX_NEW_FALLBACK)
-     fxMesa->is_in_hardware = fxIsInHardware(ctx);
+   /* Recalculate fog table on projection matrix changes.  This used to
+    * be triggered by the NearFar callback.
+    */
+   if (new_state & _NEW_PROJECTION) 
+      fxMesa->new_state |= FX_NEW_FOG;
 
-  if (fxMesa->is_in_hardware) {
-    if (fxMesa->new_state)
-      fxSetupFXUnits(ctx);
+   if (new_state & (_FX_NEW_IS_IN_HARDWARE |
+                   _FX_NEW_RENDERSTATE |
+                   _FX_NEW_SETUP_FUNCTION | 
+                   _NEW_TEXTURE))
+   {
+      fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
 
-    if (new_state & _FX_NEW_RENDERSTATE) {
-      fxDDChooseRenderState( ctx );
+      if (new_state & _FX_NEW_IS_IN_HARDWARE)
+        fxMesa->is_in_hardware = fxIsInHardware(ctx);
+    
+      if (fxMesa->new_state)
+        fxSetupFXUnits(ctx);
 
-      fxMesa->RenderVBTables=fxDDChooseRenderVBTables(ctx);
-      fxMesa->RenderVBClippedTab=fxMesa->RenderVBTables[0];
-      fxMesa->RenderVBCulledTab=fxMesa->RenderVBTables[1];
-      fxMesa->RenderVBRawTab=fxMesa->RenderVBTables[2];
-    }
+      if (new_state & _FX_NEW_RENDERSTATE) 
+        fxDDChooseRenderState( ctx );
     
-    if (new_state & _FX_NEW_SETUP_FUNCTION)
-      ctx->Driver.RasterSetup=fxDDChooseSetupFunction(ctx);      
+      if (new_state & _FX_NEW_SETUP_FUNCTION)
+        ctx->Driver.BuildProjectedVertices = fx_validate_BuildProjVerts;     
 
+      if (new_state & _NEW_TEXTURE) 
+        update_texture_scales( ctx );
 
-    ctx->Driver.PointsFunc=fxMesa->PointsFunc;
-    ctx->Driver.LineFunc=fxMesa->LineFunc;
-    ctx->Driver.TriangleFunc=fxMesa->TriangleFunc;
-    ctx->Driver.QuadFunc=fxMesa->QuadFunc;
-  } else {
-     fxMesa->render_index = FX_FALLBACK;
-  }
-}
+   }
 
-static void fxDDReducedPrimitiveChange(GLcontext *ctx, GLenum prim)
-{
-  if (ctx->Polygon.CullFlag) {
-    if (ctx->ReducedPrimitive != GL_POLYGON) { /* Lines or Points */
-      FX_grCullMode(GR_CULL_DISABLE);
-      FX_CONTEXT(ctx)->cullMode=GR_CULL_DISABLE;
-    }
-  }
+#ifdef FXVTXFMT
+   if (fxMesa->allow_vfmt) {
+      if (new_state & _NEW_LIGHT)
+        fx_update_lighting( ctx );
+
+      if (new_state & _FX_NEW_VTXFMT)
+        fxDDCheckVtxfmt( ctx );
+   }
+#endif
 }
 
-void fxSetupDDPointers(GLcontext *ctx)
+static void fxDDRenderPrimitive( GLcontext *ctx, GLenum mode )
 {
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxSetupDDPointers()\n");
-  }
-
-  ctx->Driver.UpdateStateNotify = (_FX_NEW_SETUP_FUNCTION|
-                                  _FX_NEW_RENDERSTATE|
-                                  _FX_NEW_FALLBACK|
-                                  _SWRAST_NEW_TRIANGLE|
-                                  _SWRAST_NEW_LINE|
-                                  _SWRAST_NEW_POINT);
+   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
 
-  ctx->Driver.UpdateState=fxDDUpdateDDPointers;
+   if (!fxMesa->is_in_hardware) {
+      _swsetup_RenderPrimitive( ctx, mode );
+   } 
+   else {
+      fxMesa->render_prim = mode;
+   }   
+}
 
-  ctx->Driver.WriteDepthSpan=fxDDWriteDepthSpan;
-  ctx->Driver.WriteDepthPixels=fxDDWriteDepthPixels;
-  ctx->Driver.ReadDepthSpan=fxDDReadDepthSpan;
-  ctx->Driver.ReadDepthPixels=fxDDReadDepthPixels;
-         
-  ctx->Driver.GetString=fxDDGetString;
 
-  ctx->Driver.NearFar=fxDDSetNearFar;
+static void fxDDRenderStart( GLcontext *ctx )
+{
+   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
 
-  ctx->Driver.GetParameteri=fxDDGetParameteri;
+   _swsetup_RenderStart( ctx );
 
-  ctx->Driver.ClearIndex=NULL;
-  ctx->Driver.ClearColor=fxDDClearColor;
-  ctx->Driver.Clear=fxDDClear;
+   if (fxMesa->new_state) {
+      fxSetupFXUnits( ctx );
+   }
+}
 
-  ctx->Driver.Index=NULL;
-  ctx->Driver.Color=fxDDSetColor;
+static void fxDDRenderFinish( GLcontext *ctx )
+{
+   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
 
-  ctx->Driver.SetDrawBuffer=fxDDSetDrawBuffer;
-  ctx->Driver.SetReadBuffer=fxDDSetReadBuffer;
-  ctx->Driver.GetBufferSize=fxDDBufferSize;
+   if (!fxMesa->is_in_hardware) {
+      _swsetup_RenderFinish( ctx );
+   } 
+}
 
-  ctx->Driver.Bitmap=fxDDDrawBitmap;
-  ctx->Driver.DrawPixels=NULL;
-  ctx->Driver.ReadPixels=fxDDReadPixels;
 
-  ctx->Driver.Finish=fxDDFinish;
-  ctx->Driver.Flush=NULL;
 
-  ctx->Driver.RenderStart=NULL;
-  ctx->Driver.RenderFinish=NULL;
+void fxSetupDDPointers(GLcontext *ctx)
+{
+   if (MESA_VERBOSE&VERBOSE_DRIVER) {
+      fprintf(stderr,"fxmesa: fxSetupDDPointers()\n");
+   }
 
-  ctx->Driver.TexImage2D = fxDDTexImage2D;
-  ctx->Driver.TexSubImage2D = fxDDTexSubImage2D;
-  ctx->Driver.GetTexImage = fxDDGetTexImage;
-  ctx->Driver.TexEnv=fxDDTexEnv;
-  ctx->Driver.TexParameter=fxDDTexParam;
-  ctx->Driver.BindTexture=fxDDTexBind;
-  ctx->Driver.DeleteTexture=fxDDTexDel;
-  ctx->Driver.UpdateTexturePalette=fxDDTexPalette;
+   ctx->Driver.UpdateState=fxDDUpdateDDPointers;
 
-  ctx->Driver.RectFunc=NULL;
+   ctx->Driver.WriteDepthSpan=fxDDWriteDepthSpan;
+   ctx->Driver.WriteDepthPixels=fxDDWriteDepthPixels;
+   ctx->Driver.ReadDepthSpan=fxDDReadDepthSpan;
+   ctx->Driver.ReadDepthPixels=fxDDReadDepthPixels;
 
-  ctx->Driver.AlphaFunc=fxDDAlphaFunc;
-  ctx->Driver.BlendFunc=fxDDBlendFunc;
-  ctx->Driver.DepthFunc=fxDDDepthFunc;
-  ctx->Driver.DepthMask=fxDDDepthMask;
-  ctx->Driver.ColorMask=fxDDColorMask;
-  ctx->Driver.Fogfv=fxDDFogfv;
-  ctx->Driver.Scissor=fxDDScissor;
-  ctx->Driver.FrontFace=fxDDFrontFace;
-  ctx->Driver.CullFace=fxDDCullFace;
-  ctx->Driver.ShadeModel=fxDDShadeModel;
-  ctx->Driver.Enable=fxDDEnable;
-  ctx->Driver.ReducedPrimitiveChange=fxDDReducedPrimitiveChange;
+   ctx->Driver.GetString=fxDDGetString;
 
-  ctx->Driver.RegisterVB=fxDDRegisterVB;
-  ctx->Driver.UnregisterVB=fxDDUnregisterVB;
+   ctx->Driver.ClearIndex=NULL;
+   ctx->Driver.ClearColor=fxDDClearColor;
+   ctx->Driver.Clear=fxDDClear;
 
-  ctx->Driver.RegisterPipelineStages = fxDDRegisterPipelineStages;
+   ctx->Driver.SetDrawBuffer=fxDDSetDrawBuffer;
+   ctx->Driver.SetReadBuffer=fxDDSetReadBuffer;
+   ctx->Driver.GetBufferSize=fxDDBufferSize;
 
-  ctx->Driver.OptimizeImmediatePipeline = 0; /* nothing done yet */
-  ctx->Driver.OptimizePrecalcPipeline = 0;
+   ctx->Driver.Accum = _swrast_Accum;
+   ctx->Driver.Bitmap = fxDDDrawBitmap;
+   ctx->Driver.CopyPixels = _swrast_CopyPixels;
+   ctx->Driver.DrawPixels = _swrast_DrawPixels;
+   ctx->Driver.ReadPixels = fxDDReadPixels;
+   ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers;
 
-/*    if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */
-/*       ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */
+   ctx->Driver.Finish=fxDDFinish;
+   ctx->Driver.Flush=NULL;
 
-  if (!getenv("FX_NO_FAST")) 
-      ctx->Driver.BuildPrecalcPipeline = fxDDBuildPrecalcPipeline; 
+   ctx->Driver.RenderStart=fxDDRenderStart;
+   ctx->Driver.RenderFinish=fxDDRenderFinish;
+   ctx->Driver.ResetLineStipple=_swrast_ResetLineStipple;
+   ctx->Driver.RenderPrimitive=fxDDRenderPrimitive;
 
-  ctx->Driver.TriangleCaps = DD_TRI_CULL|DD_TRI_OFFSET|DD_TRI_LIGHT_TWOSIDE;
+   /* Install the oldstyle interp functions:
+    */
+   ctx->Driver.RenderInterp = _swsetup_RenderInterp;
+   ctx->Driver.RenderCopyPV = _swsetup_RenderCopyPV;
+   ctx->Driver.RenderClippedLine = _swsetup_RenderClippedLine;
+   ctx->Driver.RenderClippedPolygon = _swsetup_RenderClippedPolygon;
+
+   ctx->Driver.TexImage2D = fxDDTexImage2D;
+   ctx->Driver.TexSubImage2D = fxDDTexSubImage2D;
+   ctx->Driver.GetTexImage = fxDDGetTexImage;
+   ctx->Driver.TexEnv=fxDDTexEnv;
+   ctx->Driver.TexParameter=fxDDTexParam;
+   ctx->Driver.BindTexture=fxDDTexBind;
+   ctx->Driver.DeleteTexture=fxDDTexDel;
+   ctx->Driver.UpdateTexturePalette=fxDDTexPalette;
+
+   ctx->Driver.AlphaFunc=fxDDAlphaFunc;
+   ctx->Driver.BlendFunc=fxDDBlendFunc;
+   ctx->Driver.DepthFunc=fxDDDepthFunc;
+   ctx->Driver.DepthMask=fxDDDepthMask;
+   ctx->Driver.ColorMask=fxDDColorMask;
+   ctx->Driver.Fogfv=fxDDFogfv;
+   ctx->Driver.Scissor=fxDDScissor;
+   ctx->Driver.FrontFace=fxDDFrontFace;
+   ctx->Driver.CullFace=fxDDCullFace;
+   ctx->Driver.ShadeModel=fxDDShadeModel;
+   ctx->Driver.Enable=fxDDEnable;
 
-  fxSetupDDSpanPointers(ctx);
+  
 
-  FX_CONTEXT(ctx)->render_index = 1; /* force an update */
-  fxDDUpdateDDPointers(ctx);
+   fxSetupDDSpanPointers(ctx);
+   fxDDUpdateDDPointers(ctx,~0);
 }
 
 
@@ -1169,6 +1141,7 @@ void fxSetupDDPointers(GLcontext *ctx)
  * Need this to provide at least one external definition.
  */
 
+extern int gl_fx_dummy_function_dd(void);
 int gl_fx_dummy_function_dd(void)
 {
   return 0;