Rename the various function types in t_context.h to include a tnl_ prefix.
[mesa.git] / src / mesa / drivers / glide / fxapi.c
index 6470affd9aa3810f0c248ea7aa791d4521118055..0dccdc2093bd61cebd0477fca97d4e140f09efbe 100644 (file)
@@ -1,10 +1,8 @@
-/* -*- mode: C; tab-width:8;  -*- */
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.3
+ * Version:  4.0
  *
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2001  Brian Paul   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"),
  * BRIAN PAUL 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.
- *
- *
- * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
- * terms stated above.
- *
- * Thank you for your contribution, David!
- *
- * Please make note of the above copyright/license statement.  If you
- * contributed code or bug fixes to this code under the previous (GNU
- * Library) license and object to the new license, your code will be
- * removed at your request.  Please see the Mesa docs/COPYRIGHT file
- * for more information.
- *
- * Additional Mesa/3Dfx driver developers:
- *   Daryll Strauss <daryll@precisioninsight.com>
- *   Keith Whitwell <keith@precisioninsight.com>
- *
- * See fxapi.h for more revision/author details.
  */
 
+/* Authors:
+ *    David Bucciarelli
+ *    Brian Paul
+ *    Daryll Strauss
+ *    Keith Whitwell
+ *    Daniel Borca
+ *    Hiroshi Morii
+ */
+
+
+/* fxapi.c - public interface to FX/Mesa functions (fxmesa.h) */
+
 
 #ifdef HAVE_CONFIG_H
 #include "conf.h"
 #if defined(FX)
 #include "fxdrv.h"
 
-static fxMesaContext fxMesaCurrentCtx=NULL;
+#include "drivers/common/driverfuncs.h"
+
+#ifndef TDFX_DEBUG
+int TDFX_DEBUG = (0 
+/*               | VERBOSE_VARRAY */
+/*               | VERBOSE_TEXTURE */
+/*               | VERBOSE_IMMEDIATE */
+/*               | VERBOSE_PIPELINE */
+/*               | VERBOSE_DRIVER */
+/*               | VERBOSE_STATE */
+/*               | VERBOSE_API */
+/*               | VERBOSE_DISPLAY_LIST */
+/*               | VERBOSE_LIGHTING */
+/*               | VERBOSE_PRIMS */
+/*               | VERBOSE_VERTS */
+   );
+#endif
+
+static fxMesaContext fxMesaCurrentCtx = NULL;
 
 /*
  * Status of 3Dfx hardware initialization
  */
 
-static int glbGlideInitialized=0;
-static int glb3DfxPresent=0;
-static int glbTotNumCtx=0;
+static int glbGlideInitialized = 0;
+static int glb3DfxPresent = 0;
+static int glbTotNumCtx = 0;
 
-GrHwConfiguration glbHWConfig;
-int glbCurrentBoard=0;
+static GrHwConfiguration glbHWConfig;
+static int glbCurrentBoard = 0;
 
 
 #if defined(__WIN32__)
-static int cleangraphics(void)
+static int
+cleangraphics(void)
 {
-  glbTotNumCtx=1;
-  fxMesaDestroyContext(fxMesaCurrentCtx);
+   glbTotNumCtx = 1;
+   fxMesaDestroyContext(fxMesaCurrentCtx);
 
-  return 0;
+   return 0;
 }
 #elif defined(__linux__)
-static void cleangraphics(void)
+static void
+cleangraphics(void)
 {
-  glbTotNumCtx=1;
-  fxMesaDestroyContext(fxMesaCurrentCtx);
+   glbTotNumCtx = 1;
+   fxMesaDestroyContext(fxMesaCurrentCtx);
 }
 
-static void cleangraphics_handler(int s)
+static void
+cleangraphics_handler(int s)
 {
-  fprintf(stderr,"fxmesa: Received a not handled signal %d\n",s);
+   fprintf(stderr, "fxmesa: ERROR: received a not handled signal %d\n", s);
 
-  cleangraphics();
+   cleangraphics();
 /*    abort(); */
-  exit(1);
+   exit(1);
 }
 #endif
 
 
+/*
+ * Query 3Dfx hardware presence/kind
+ */
+static GLboolean GLAPIENTRY fxQueryHardware (void)
+{
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+    fprintf(stderr, "fxQueryHardware()\n");
+ }
+
+ if (!glbGlideInitialized) {
+    grGlideInit();
+    glb3DfxPresent = FX_grSstQueryHardware(&glbHWConfig);
+
+    glbGlideInitialized = 1;
+
+#if defined(__WIN32__)
+    _onexit((_onexit_t) cleangraphics);
+#elif defined(__linux__)
+    /* Only register handler if environment variable is not defined. */
+    if (!getenv("MESA_FX_NO_SIGNALS")) {
+       atexit(cleangraphics);
+    }
+#endif
+ }
+
+ return glb3DfxPresent;
+}
+
+
 /*
  * Select the Voodoo board to use when creating
  * a new context.
  */
-GLboolean GLAPIENTRY fxMesaSelectCurrentBoard(int n)
+GLint GLAPIENTRY fxMesaSelectCurrentBoard (int n)
 {
-  fxQueryHardware();
+   fxQueryHardware();
+
+   if ((n < 0) || (n >= glbHWConfig.num_sst))
+      return -1;
 
-  if((n<0) || (n>=glbHWConfig.num_sst))
-    return GL_FALSE;
+   return glbHWConfig.SSTs[glbCurrentBoard = n].type;
+}
 
-  glbCurrentBoard=n;
 
-  return GL_TRUE;
+fxMesaContext GLAPIENTRY fxMesaGetCurrentContext (void)
+{
+ return fxMesaCurrentCtx;
 }
 
 
-fxMesaContext GLAPIENTRY fxMesaGetCurrentContext(void)
+void GLAPIENTRY fxGetScreenGeometry (GLint *w, GLint *h)
 {
-  return fxMesaCurrentCtx;
+ GLint width = 0;
+ GLint height = 0;
+ if (fxMesaCurrentCtx != NULL) {
+    width = fxMesaCurrentCtx->screen_width;
+    height = fxMesaCurrentCtx->screen_height;
+ }
+
+ if (w != NULL) {
+    *w = width;
+ }
+ if (h != NULL) {
+    *h = height;
+ }
 }
 
 
@@ -118,712 +177,768 @@ fxMesaContext GLAPIENTRY fxMesaGetCurrentContext(void)
  * More a trick than a real extesion, use the shared global
  * palette extension. 
  */
-extern void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *pal); /* silence warning */
-void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *pal)
+extern void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint * pal);      /* silence warning */
+void GLAPIENTRY
+gl3DfxSetPaletteEXT(GLuint * pal)
 {
-  fxMesaContext fxMesa =fxMesaCurrentCtx;
-  
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    int i;
-
-    fprintf(stderr,"fxmesa: gl3DfxSetPaletteEXT()\n");
-
-    for(i=0;i<256;i++)
-      fprintf(stderr,"%x\n",pal[i]);
-  }
-  
-  if(fxMesa) {
-    fxMesa->haveGlobalPaletteTexture=1;
-    
-    FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal);
-    if (fxMesa->haveTwoTMUs)
-        FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal);
-  }
-}
+   fxMesaContext fxMesa = fxMesaCurrentCtx;
 
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      int i;
 
-static GrScreenResolution_t fxBestResolution(int width, int height, int aux)
-{
-  static int resolutions[][5]={ 
-    { 320, 200, GR_RESOLUTION_320x200, 2, 2 },
-    { 320, 240, GR_RESOLUTION_320x240, 2, 2 },
-    { 512, 384, GR_RESOLUTION_512x384, 2, 2 },
-    { 640, 400, GR_RESOLUTION_640x400, 2, 2 },
-    { 640, 480, GR_RESOLUTION_640x480, 2, 2 },
-    { 800, 600, GR_RESOLUTION_800x600, 4, 2 },
-    { 960, 720, GR_RESOLUTION_960x720, 6, 4 }
-#ifdef GR_RESOLUTION_1024x768
-    ,{ 1024, 768, GR_RESOLUTION_1024x768, 8, 4 }
-#endif
-#ifdef GR_RESOLUTION_1280x1024
-    ,{ 1280, 1024, GR_RESOLUTION_1280x1024, 8, 8 }
-#endif
-#ifdef GR_RESOLUTION_1600x1200
-    ,{ 1600, 1200, GR_RESOLUTION_1600x1200, 16, 8 }
-#endif
-  };
-  int NUM_RESOLUTIONS = sizeof(resolutions) / (sizeof(int)*5);
-  int i,fbmem;
-  GrScreenResolution_t lastvalidres=resolutions[4][2];
-
-  fxQueryHardware();
+      fprintf(stderr, "gl3DfxSetPaletteEXT(...)\n");
 
-  if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
-    fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam;
+      for (i = 0; i < 256; i++) {
+        fprintf(stderr, "\t%x\n", pal[i]);
+      }
+   }
 
-    if(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect)
-      fbmem*=2;
-  } else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96)
-    fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam;
-  else
-    fbmem=2;
+   if (fxMesa) {
+      fxMesa->haveGlobalPaletteTexture = 1;
 
-  /* A work around for BZFlag */
+      grTexDownloadTable(GR_TEXTABLE_PALETTE, (GuTexPalette *) pal);
+   }
+}
 
-  if((width==1) && (height==1)) {
-    width=640;
-    height=480;
-  }
 
-  for(i=0;i<NUM_RESOLUTIONS;i++)
-    if(resolutions[i][4-aux]<=fbmem) {
-      if((width<=resolutions[i][0]) && (height<=resolutions[i][1]))
-        return resolutions[i][2];
+static GrScreenResolution_t fxBestResolution (int width, int height)
+{
+ static int resolutions[][3] = {
+        { GR_RESOLUTION_320x200,    320,  200 },
+        { GR_RESOLUTION_320x240,    320,  240 },
+        { GR_RESOLUTION_400x256,    400,  256 },
+        { GR_RESOLUTION_512x384,    512,  384 },
+        { GR_RESOLUTION_640x200,    640,  200 },
+        { GR_RESOLUTION_640x350,    640,  350 },
+        { GR_RESOLUTION_640x400,    640,  400 },
+        { GR_RESOLUTION_640x480,    640,  480 },
+        { GR_RESOLUTION_800x600,    800,  600 },
+        { GR_RESOLUTION_960x720,    960,  720 },
+        { GR_RESOLUTION_856x480,    856,  480 },
+        { GR_RESOLUTION_512x256,    512,  256 },
+        { GR_RESOLUTION_1024x768,  1024,  768 },
+        { GR_RESOLUTION_1280x1024, 1280, 1024 },
+        { GR_RESOLUTION_1600x1200, 1600, 1200 },
+        { GR_RESOLUTION_400x300,    400,  300 },
+        { GR_RESOLUTION_1152x864,  1152,  864 },
+        { GR_RESOLUTION_1280x960,  1280,  960 },
+        { GR_RESOLUTION_1600x1024, 1600, 1024 },
+        { GR_RESOLUTION_1792x1344, 1792, 1344 },
+        { GR_RESOLUTION_1856x1392, 1856, 1392 },
+        { GR_RESOLUTION_1920x1440, 1920, 1440 },
+        { GR_RESOLUTION_2048x1536, 2048, 1536 },
+        { GR_RESOLUTION_2048x2048, 2048, 2048 }
+ };
+
+ int i, size;
+ int lastvalidres = GR_RESOLUTION_640x480;
+ int min = 2048 * 2048; /* max is GR_RESOLUTION_2048x2048 */
+ GrResolution resTemplate = {
+              GR_QUERY_ANY,
+              GR_QUERY_ANY,
+              2 /*GR_QUERY_ANY */,
+              GR_QUERY_ANY
+ };
+ GrResolution *presSupported;
+
+ fxQueryHardware();
+
+ size = grQueryResolutions(&resTemplate, NULL);
+ presSupported = malloc(size);
+        
+ size /= sizeof(GrResolution);
+ grQueryResolutions(&resTemplate, presSupported);
+
+ for (i = 0; i < size; i++) {
+     int r = presSupported[i].resolution;
+     if ((width <= resolutions[r][1]) && (height <= resolutions[r][2])) {
+        if (min > (resolutions[r][1] * resolutions[r][2])) {
+           min = resolutions[r][1] * resolutions[r][2];
+           lastvalidres = r;
+        }
+     }
+ }
 
-      lastvalidres=resolutions[i][2];
-    }
+ free(presSupported);
 
 return lastvalidres;
return resolutions[lastvalidres][0];
 }
 
 
-fxMesaContext GLAPIENTRY fxMesaCreateBestContext(GLuint win,GLint width, GLint height,
-                                              const GLint attribList[])
+fxMesaContext GLAPIENTRY
+fxMesaCreateBestContext(GLuint win, GLint width, GLint height,
+                       const GLint attribList[])
 {
-  GrScreenRefresh_t refresh;
-  int i;
-  int res,aux;
-  refresh=GR_REFRESH_75Hz;
-
-  if(getenv("SST_SCREENREFRESH")) {
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"60"))
-      refresh=GR_REFRESH_60Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"70"))
-      refresh=GR_REFRESH_70Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"72"))
-      refresh=GR_REFRESH_72Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"75"))
-      refresh=GR_REFRESH_75Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"80"))
-      refresh=GR_REFRESH_80Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"85"))
-      refresh=GR_REFRESH_85Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"90"))
-      refresh=GR_REFRESH_90Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"100"))
-      refresh=GR_REFRESH_100Hz;
-    if(!strcmp(getenv("SST_SCREENREFRESH"),"120"))
-      refresh=GR_REFRESH_120Hz;
-  }
-
-  aux=0;
-  for(i=0;attribList[i]!=FXMESA_NONE;i++)
-    if((attribList[i]==FXMESA_ALPHA_SIZE) ||
-       (attribList[i]==FXMESA_DEPTH_SIZE)) {
-      if(attribList[++i]>0) {
-        aux=1;
-        break;
-      }
-    }
+ int res = fxBestResolution(width, height);
 
-  res=fxBestResolution(width,height,aux);
+ if (res == -1) {
+    return NULL;
+ }
 
 return fxMesaCreateContext(win,res,refresh,attribList);
return fxMesaCreateContext(win, res, GR_REFRESH_60Hz, attribList);
 }
 
 
-#if 0
-void fxsignals()
-{
-   signal(SIGINT,SIG_IGN);
-   signal(SIGHUP,SIG_IGN);
-   signal(SIGPIPE,SIG_IGN);
-   signal(SIGFPE,SIG_IGN);
-   signal(SIGBUS,SIG_IGN);
-   signal(SIGILL,SIG_IGN);
-   signal(SIGSEGV,SIG_IGN);
-   signal(SIGTERM,SIG_IGN);
-}
-#endif
-
 /*
  * Create a new FX/Mesa context and return a handle to it.
  */
-fxMesaContext GLAPIENTRY fxMesaCreateContext(GLuint win,
-                                             GrScreenResolution_t res,
-                                             GrScreenRefresh_t ref,
-                                             const GLint attribList[])
+fxMesaContext GLAPIENTRY
+fxMesaCreateContext(GLuint win,
+                   GrScreenResolution_t res,
+                   GrScreenRefresh_t ref, const GLint attribList[])
 {
-   fxMesaContext fxMesa = NULL;
-   int i,type;
-   int aux;
-   GLboolean doubleBuffer=GL_FALSE;
-   GLboolean alphaBuffer=GL_FALSE;
-   GLboolean verbose=GL_FALSE;
-   GLint depthSize=0;
-   GLint stencilSize=0;
-   GLint accumSize=0;
-   GLcontext *shareCtx = NULL;
-   GLcontext *ctx = 0;
-   /*FX_GrContext_t glideContext = 0;*/
-   char *errorstr;
-   GLboolean useBGR;
-   char *system = NULL;
-
-   if (MESA_VERBOSE&VERBOSE_DRIVER) {
-      fprintf(stderr,"fxmesa: fxMesaCreateContext() Start\n");
-   }
-
-   if(getenv("MESA_FX_INFO"))
-      verbose=GL_TRUE;
-
-   aux=0;
-   i=0;
-   while(attribList[i]!=FXMESA_NONE) {
-      switch (attribList[i]) {
-      case FXMESA_DOUBLEBUFFER:
-        doubleBuffer=GL_TRUE;
-        break;
-      case FXMESA_ALPHA_SIZE:
-        i++;
-        alphaBuffer=attribList[i]>0;
-        if(alphaBuffer)
-           aux=1;
-        break;
-      case FXMESA_DEPTH_SIZE:
-        i++;
-        depthSize=attribList[i];
-        if(depthSize) {
-           aux=1;
-            depthSize = 16;
-         }
-        break;
-      case FXMESA_STENCIL_SIZE:
-        i++;
-        stencilSize=attribList[i];
-        break;
-      case FXMESA_ACCUM_SIZE:
-        i++;
-        accumSize=attribList[i];
-        break;
-        /* XXX ugly hack here for sharing display lists */
-#define FXMESA_SHARE_CONTEXT 990099  /* keep in sync with xmesa1.c! */
-      case FXMESA_SHARE_CONTEXT:
-        i++;
-        {
-           const void *vPtr = &attribList[i];
-           GLcontext **ctx = (GLcontext **) vPtr;
-           shareCtx = *ctx;
-        }
-        break;
-      default:
-        if (MESA_VERBOSE&VERBOSE_DRIVER) {
-           fprintf(stderr,"fxmesa: fxMesaCreateContext() End (defualt)\n");
-        }
-        return NULL;
-      }
-      i++;
-   }
-
-   /* A workaround for Linux GLQuake */
-   if(depthSize && alphaBuffer)
-      alphaBuffer=0;
-
-   if ((type=fxQueryHardware()) < 0) {
-      fprintf(stderr,"fx Driver: ERROR no Voodoo1/2 Graphics or Voodoo Rush !\n");
-      return NULL;
-   }
-
-   if(type==GR_SSTTYPE_VOODOO)
-      win=0;
-
-   grSstSelect(glbCurrentBoard);
-
-   fxMesa=(fxMesaContext)calloc(1,sizeof(struct tfxMesaContext));
-   if(!fxMesa) {
-      errorstr = "malloc";
-      goto errorhandler;
+ fxMesaContext fxMesa = NULL;
+ GLcontext *ctx = NULL, *shareCtx = NULL;
+ struct dd_function_table functions;
+
+ int i;
+ const char *str;
+ int sliaa, numSLI, samplesPerChip;
+ struct SstCard_St *voodoo;
+ struct tdfx_glide *Glide;
+
+ GLboolean aux;
+ GLboolean doubleBuffer;
+ GLuint colDepth;
+ GLuint depthSize, alphaSize, stencilSize, accumSize;
+ GLuint redBits, greenBits, blueBits, alphaBits;
+ GrPixelFormat_t pixFmt;
+   
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+    fprintf(stderr, "fxMesaCreateContext(...)\n");
+ }
+
+ /* Okay, first process the user flags */
+ aux = GL_FALSE;
+ doubleBuffer = GL_FALSE;
+ colDepth = 16;
+ depthSize = alphaSize = stencilSize = accumSize = 0;
+
+ i = 0;
+ while (attribList[i] != FXMESA_NONE) {
+       switch (attribList[i]) {
+              case FXMESA_COLORDEPTH:
+                  colDepth = attribList[++i];
+                  break;
+              case FXMESA_DOUBLEBUFFER:
+                  doubleBuffer = GL_TRUE;
+                  break;
+              case FXMESA_ALPHA_SIZE:
+                  if ((alphaSize = attribList[++i])) {
+                     aux = GL_TRUE;
+                   }
+                  break;
+              case FXMESA_DEPTH_SIZE:
+                  if ((depthSize = attribList[++i])) {
+                     aux = GL_TRUE;
+                   }
+                  break;
+              case FXMESA_STENCIL_SIZE:
+                  stencilSize = attribList[++i];
+                  break;
+              case FXMESA_ACCUM_SIZE:
+                  accumSize = attribList[++i];
+                  break;
+              /* XXX ugly hack here for sharing display lists */
+              case FXMESA_SHARE_CONTEXT:
+                   shareCtx = (GLcontext *)attribList[++i];
+                  break;
+              default:
+                   fprintf(stderr, "fxMesaCreateContext: ERROR: wrong parameter (%d) passed\n", attribList[i]);
+                  return NULL;
+       }
+       i++;
+ }
+
+ if (!fxQueryHardware()) {
+    str = "no Voodoo hardware!";
+    goto errorhandler;
+ }
+
+ grSstSelect(glbCurrentBoard);
+ /*grEnable(GR_OPENGL_MODE_EXT);*/ /* ZZZ: trick to make GL happy.
+                                  Glide3 will unmap memory for card when grSstWinClose is called.
+                                  This also forces the SLI band height to be 32 (above 1024x768) or 16
+                                  and disables the splash screen due to y-origin swapping.
+                                  Note: We only want the former. */
+ voodoo = &glbHWConfig.SSTs[glbCurrentBoard];
+
+ fxMesa = (fxMesaContext)CALLOC_STRUCT(tfxMesaContext);
+ if (!fxMesa) {
+    str = "private context";
+    goto errorhandler;
+ }
+
+ if (getenv("MESA_FX_INFO")) {
+    fxMesa->verbose = GL_TRUE;
+ }
+
+ fxMesa->type = voodoo->type;
+ fxMesa->HavePalExt = voodoo->HavePalExt && !getenv("MESA_FX_IGNORE_PALEXT");
+ fxMesa->HavePixExt = voodoo->HavePixExt && !getenv("MESA_FX_IGNORE_PIXEXT");
+ fxMesa->HaveTexFmt = voodoo->HaveTexFmt && !getenv("MESA_FX_IGNORE_TEXFMT");
+ fxMesa->HaveCmbExt = voodoo->HaveCmbExt && !getenv("MESA_FX_IGNORE_CMBEXT");
+ fxMesa->HaveMirExt = voodoo->HaveMirExt && !getenv("MESA_FX_IGNORE_MIREXT");
+ fxMesa->HaveTexUma = voodoo->HaveTexUma && !getenv("MESA_FX_IGNORE_TEXUMA");
+ fxMesa->Glide = glbHWConfig.Glide;
+ Glide = &fxMesa->Glide;
+ fxMesa->HaveTexus2 = Glide->txImgQuantize &&
+                      Glide->txMipQuantize &&
+                      Glide->txPalToNcc && !getenv("MESA_FX_IGNORE_TEXUS2");
+
+ /* Determine if we need vertex swapping, RGB order and SLI/AA */
+ sliaa = 0;
+ switch (fxMesa->type) {
+        case GR_SSTTYPE_VOODOO:
+        case GR_SSTTYPE_SST96:
+        case GR_SSTTYPE_Banshee:
+             fxMesa->bgrOrder = GL_TRUE;
+             fxMesa->snapVertices = GL_TRUE;
+             break;
+        case GR_SSTTYPE_Voodoo2:
+             fxMesa->bgrOrder = GL_TRUE;
+             fxMesa->snapVertices = GL_FALSE;
+             break;
+        case GR_SSTTYPE_Voodoo4:
+        case GR_SSTTYPE_Voodoo5:
+             /* number of SLI units and AA Samples per chip */
+             if ((str = Glide->grGetRegistryOrEnvironmentStringExt("SSTH3_SLI_AA_CONFIGURATION")) != NULL) {
+                sliaa = atoi(str);
+             }
+        case GR_SSTTYPE_Voodoo3:
+        default:
+             fxMesa->bgrOrder = GL_FALSE;
+             fxMesa->snapVertices = GL_FALSE;
+             break;
+ }
+ /* ZZZ TO DO: Add the old SLI/AA settings for Napalm. */
+ switch(voodoo->numChips) {
+ case 4: /* 4 chips */
+   switch(sliaa) {
+   case 8: /* 8 Sample AA */
+     numSLI         = 1;
+     samplesPerChip = 2;
+     break;
+   case 7: /* 4 Sample AA */
+     numSLI         = 1;
+     samplesPerChip = 1;
+     break;
+   case 6: /* 2 Sample AA */
+     numSLI         = 2;
+     samplesPerChip = 1;
+     break;
+   default:
+     numSLI         = 4;
+     samplesPerChip = 1;
    }
-
-   if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO)
-      fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx > 1);
-   else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96)
-      fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx > 1);
-   else
-      fxMesa->haveTwoTMUs=GL_FALSE;
-
-   fxMesa->haveDoubleBuffer=doubleBuffer;
-   fxMesa->haveAlphaBuffer=alphaBuffer;
-   fxMesa->haveGlobalPaletteTexture=GL_FALSE;
-   fxMesa->haveZBuffer=depthSize ? 1 : 0;
-   fxMesa->verbose=verbose;
-   fxMesa->board=glbCurrentBoard;
-
-
-   fxMesa->glideContext = FX_grSstWinOpen((FxU32)win,res,ref,
-#if  FXMESA_USE_ARGB
-                                         GR_COLORFORMAT_ARGB,
-#else
-                                         GR_COLORFORMAT_ABGR,
-#endif
-                                         GR_ORIGIN_LOWER_LEFT,
-                                         2,aux);
-   if (!fxMesa->glideContext){
-      errorstr = "grSstWinOpen"; 
-      goto errorhandler;
+   break;
+ case 2: /* 2 chips */
+   switch(sliaa) {
+   case 4: /* 4 Sample AA */
+     numSLI         = 1;
+     samplesPerChip = 2;
+     break;
+   case 3: /* 2 Sample AA */
+     numSLI         = 1;
+     samplesPerChip = 1;
+     break;
+   default:
+     numSLI         = 2;
+     samplesPerChip = 1;
    }
-
-   /*
-    * Pixel tables are use during pixel read-back
-    * Either initialize them for RGB or BGR order.
-    */
-#if FXMESA_USE_ARGB 
-   useBGR = GL_FALSE; /* Force RGB pixel order */       
-   system = "FXMESA_USE_ARGB";
-#else
-   if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) {
-      /* jk991130 - Voodoo 3s don't use BGR. Query the # of TMUs
-       * as Voodoo3s have 2 TMUs on board, Banshee has only 1
-       * bk000413 - another suggestion from Joseph Kain is using
-       *  VendorID 0x121a for all 3dfx boards
-       *   DeviceID VG  1/V2  2/VB  3/V3  5
-       * For now we cehck for known BGR devices, and presume
-       *  everything else to be a V3/RGB.
-       */
-      GrVoodooConfig_t *voodoo;
-      voodoo = &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig;
-
-      if (voodoo->nTexelfx == 1) {
-         /* Voodoo1 or Banshee */
-         useBGR = GL_TRUE;
-         system = "Voodoo1";
-      }
-      else if (voodoo->nTexelfx == 2 &&
-               voodoo->fbiRev == 260 &&
-               voodoo->tmuConfig[0].tmuRev == 4 &&
-               (voodoo->tmuConfig[0].tmuRam == 2 ||
-                voodoo->tmuConfig[0].tmuRam == 4)) {
-         /* Voodoo 2 */
-         useBGR = GL_TRUE;
-         system = "Voodoo2";
-      }
-      else if (voodoo->nTexelfx == 2 &&
-               voodoo->fbiRev == 2 &&
-               voodoo->tmuConfig[0].tmuRev == 1 &&
-               voodoo->tmuConfig[0].tmuRam == 4) {
-         /* Quantum3D Obsidian 50/100 */
-         useBGR = GL_TRUE;
-         system = "Quantum3D Obsidian";
-      }
-      else 
-         /* Brian
-          *       (voodoo->nTexelfx == 2 &&
-          *        voodoo->fbiRev == 0 &&
-          *        voodoo->tmuConfig[0].tmuRev == 148441048 &&
-          *        voodoo->tmuConfig[0].tmuRam == 3)
-          * Bernd 
-          *       (voodoo->nTexelfx == 2 &&
-          *        voodoo->fbiRev ==  69634 &&
-          *        voodoo->tmuConfig[0].tmuRev == 69634 &&
-          *        voodoo->tmuConfig[0].tmuRam == 2 )
-          */
-      {
-         /* Presumed Voodoo3 */
-         useBGR =  GL_FALSE;
-         system = "Voodoo3";
-      }
-      if (getenv("MESA_FX_INFO")) { 
-        printf("Voodoo: Texelfx: %d / FBI Rev.: %d / TMU Rev.: %d / TMU RAM: %d\n",
-               voodoo->nTexelfx,
-               voodoo->fbiRev,
-               voodoo->tmuConfig[0].tmuRev,
-               voodoo->tmuConfig[0].tmuRam );
-      }
-   }
-   else {
-      useBGR = GL_FALSE; /* use RGB pixel order otherwise */
-      system = "non-voodoo";
+   break;
+ default: /* 1 chip */
+   switch(sliaa) {
+   case 1: /* 2 Sample AA */
+     numSLI         = 1;
+     samplesPerChip = 2;
+     break;
+   default:
+     numSLI         = 1;
+     samplesPerChip = 1;
    }
-#endif /*FXMESA_USE_ARGB*/
-
-   if (getenv("MESA_FX_INFO")) 
-      printf("Voodoo pixel order: %s (%s)\n", useBGR ? "BGR" : "RGB", system);
-
-   fxInitPixelTables(fxMesa, useBGR);
-
-   fxMesa->width=FX_grSstScreenWidth();
-   fxMesa->height=FX_grSstScreenHeight();
-
+ }
+
+ fxMesa->fsaa = samplesPerChip * voodoo->numChips / numSLI; /* 1:noFSAA, 2:2xFSAA, 4:4xFSAA, 8:8xFSAA */
+
+ switch (fxMesa->colDepth = colDepth) {
+   case 15:
+     redBits   = 5;
+     greenBits = 5;
+     blueBits  = 5;
+     alphaBits = depthSize ? 1 : 8;
+     switch(fxMesa->fsaa) {
+       case 8:
+         pixFmt = GR_PIXFMT_AA_8_ARGB_1555;
+         break;
+       case 4:
+         pixFmt = GR_PIXFMT_AA_4_ARGB_1555;
+         break;
+       case 2:
+         pixFmt = GR_PIXFMT_AA_2_ARGB_1555;
+         break;
+       default:
+         pixFmt = GR_PIXFMT_ARGB_1555;
+     }
+     break;
+   case 16:
+     redBits   = 5;
+     greenBits = 6;
+     blueBits  = 5;
+     alphaBits = depthSize ? 0 : 8;
+     switch(fxMesa->fsaa) {
+       case 8:
+         pixFmt = GR_PIXFMT_AA_8_RGB_565;
+         break;
+       case 4:
+         pixFmt = GR_PIXFMT_AA_4_RGB_565;
+         break;
+       case 2:
+         pixFmt = GR_PIXFMT_AA_2_RGB_565;
+         break;
+       default:
+         pixFmt = GR_PIXFMT_RGB_565;
+     }
+     break;
+   case 24:
+     fxMesa->colDepth = 32;
+   case 32:
+     redBits   = 8;
+     greenBits = 8;
+     blueBits  = 8;
+     alphaBits = 8;
+     switch(fxMesa->fsaa) {
+       case 8:
+         pixFmt = GR_PIXFMT_AA_8_ARGB_8888;
+         break;
+       case 4:
+         pixFmt = GR_PIXFMT_AA_4_ARGB_8888;
+         break;
+       case 2:
+         pixFmt = GR_PIXFMT_AA_2_ARGB_8888;
+         break;
+       default:
+         pixFmt = GR_PIXFMT_ARGB_8888;
+     }
+     break;
+   default:
+     str = "pixelFormat";
+     goto errorhandler;
+ }
+
+ /* ZZZ TODO: check if there is enough fbRam */
+
+ /* Tips:
+  * 1. we don't bother setting/checking AUX for stencil, because we'll decide
+  *    later whether we have HW stencil, based on depth buffer (thus AUX is
+  *    properly set)
+  * 2. when both DEPTH and ALPHA are enabled, depth should win. However, it is
+  *    not clear whether 15bpp and 32bpp require AUX alpha buffer. Furthermore,
+  *    alpha buffering is required only if destination alpha is used in alpha
+  *    blending; alpha blending modes that do not use destination alpha can be
+  *    used w/o alpha buffer.
+  * 3. `alphaBits' is what we can provide
+  *    `alphaSize' is what app requests
+  *    if we cannot provide enough bits for alpha buffer, we should fallback to
+  *    SW alpha. However, setting `alphaBits' to `alphaSize' might confuse some
+  *    of the span functions...
+  */
+
+ fxMesa->haveHwAlpha = GL_FALSE;
+ if (alphaSize && (alphaSize <= alphaBits)) {
+    alphaSize = alphaBits;
+    fxMesa->haveHwAlpha = GL_TRUE;
+ }
+
+ fxMesa->haveHwStencil = (fxMesa->HavePixExt && stencilSize && depthSize == 24);
+
+ fxMesa->haveZBuffer = depthSize > 0;
+ fxMesa->haveDoubleBuffer = doubleBuffer;
+ fxMesa->haveGlobalPaletteTexture = GL_FALSE;
+ fxMesa->board = glbCurrentBoard;
+
+ fxMesa->haveTwoTMUs = (voodoo->nTexelfx > 1);
+
+ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_NUM_TMU"))) {
+    if (atoi(str) <= 1) {
+       fxMesa->haveTwoTMUs = GL_FALSE;
+    }
+ }
+
+ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPPENDINGCOUNT"))) {
+    fxMesa->maxPendingSwapBuffers = atoi(str);
+    if (fxMesa->maxPendingSwapBuffers > 3) {
+       fxMesa->maxPendingSwapBuffers = 3;
+    } else if (fxMesa->maxPendingSwapBuffers < 0) {
+       fxMesa->maxPendingSwapBuffers = 0;
+    }
+ } else {
+    fxMesa->maxPendingSwapBuffers = 2;
+ }
+
+ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPINTERVAL"))) {
+    fxMesa->swapInterval = atoi(str);
+ } else {
+    fxMesa->swapInterval = 0;
+ }
+
+ BEGIN_BOARD_LOCK();
+ if (fxMesa->HavePixExt) {
+    fxMesa->glideContext = Glide->grSstWinOpenExt((FxU32)win, res, ref,
+                                                  GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT,
+                                                  pixFmt,
+                                                  2, aux);
+ } else if (pixFmt == GR_PIXFMT_RGB_565) {
+    fxMesa->glideContext = grSstWinOpen((FxU32)win, res, ref,
+                                        GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT,
+                                        2, aux);
+ } else {
+    fxMesa->glideContext = 0;
+ }
+ END_BOARD_LOCK();
+ if (!fxMesa->glideContext) {
+    str = "grSstWinOpen";
+    goto errorhandler;
+ }
+
+   /* screen */
+   fxMesa->screen_width = FX_grSstScreenWidth();
+   fxMesa->screen_height = FX_grSstScreenHeight();
+
+   /* window inside screen */
+   fxMesa->width = fxMesa->screen_width;
+   fxMesa->height = fxMesa->screen_height;
+
+   /* scissor inside window */
    fxMesa->clipMinX = 0;
    fxMesa->clipMaxX = fxMesa->width;
    fxMesa->clipMinY = 0;
    fxMesa->clipMaxY = fxMesa->height;
 
-   fxMesa->screen_width = fxMesa->width;
-   fxMesa->screen_height = fxMesa->height;
-   
-   fxMesa->new_state = ~0;
-
-   if(verbose)
-      fprintf(stderr,"Voodoo Glide screen size: %dx%d\n",
-              (int)FX_grSstScreenWidth(),(int)FX_grSstScreenHeight());
-
-   fxMesa->glVis=_mesa_create_visual(GL_TRUE,     /* RGB mode */
-                                     doubleBuffer,
-                                     GL_FALSE,    /* stereo */
-                                     5,6,5,0,     /* RGBA bits */
-                                     0,           /* index bits */
-                                     depthSize,   /* depth_size */
-                                     stencilSize, /* stencil_size */
-                                     accumSize, accumSize, accumSize, accumSize,
-                                     1 );
+   if (fxMesa->verbose) {
+      FxI32 tmuRam, fbRam;
+
+      /* Not that it matters, but tmuRam and fbRam change after grSstWinOpen. */
+      tmuRam = voodoo->tmuConfig[GR_TMU0].tmuRam;
+      fbRam  = voodoo->fbRam;
+      BEGIN_BOARD_LOCK();
+      grGet(GR_MEMORY_TMU, 4, &tmuRam);
+      grGet(GR_MEMORY_FB, 4, &fbRam);
+      END_BOARD_LOCK();
+
+      fprintf(stderr, "Voodoo Using Glide %s\n", grGetString(GR_VERSION));
+      fprintf(stderr, "Voodoo Board: %d/%d, %s, %d GPU\n",
+                      fxMesa->board + 1,
+                      glbHWConfig.num_sst,
+                      grGetString(GR_HARDWARE),
+                      voodoo->numChips);
+      fprintf(stderr, "Voodoo Memory: FB = %ld, TM = %d x %ld\n",
+                      fbRam,
+                      voodoo->nTexelfx,
+                      tmuRam);
+      fprintf(stderr, "Voodoo Screen: %dx%d:%d %s, %svertex snapping\n",
+                     fxMesa->screen_width,
+                      fxMesa->screen_height,
+                      colDepth,
+                      fxMesa->bgrOrder ? "BGR" : "RGB",
+                      fxMesa->snapVertices ? "" : "no ");
+   }
+
+  sprintf(fxMesa->rendererString, "Mesa %s v0.61 %s%s",
+          grGetString(GR_RENDERER),
+          grGetString(GR_HARDWARE),
+          ((fxMesa->type < GR_SSTTYPE_Voodoo4) && (voodoo->numChips > 1)) ? " SLI" : "");
+
+   fxMesa->glVis = _mesa_create_visual(GL_TRUE,                /* RGB mode */
+                                      doubleBuffer,
+                                      GL_FALSE,        /* stereo */
+                                      redBits,         /* RGBA.R bits */
+                                      greenBits,       /* RGBA.G bits */
+                                      blueBits,        /* RGBA.B bits */
+                                      alphaSize,       /* RGBA.A bits */
+                                      0,               /* index bits */
+                                      depthSize,       /* depth_size */
+                                      stencilSize,     /* stencil_size */
+                                      accumSize,
+                                      accumSize,
+                                      accumSize,
+                                      alphaSize ? accumSize : 0,
+                                       1);
    if (!fxMesa->glVis) {
-      errorstr = "_mesa_create_visual";
+      str = "_mesa_create_visual";
       goto errorhandler;
    }
 
-   ctx = fxMesa->glCtx=_mesa_create_context(fxMesa->glVis,
-                                        shareCtx,  /* share list context */
-                                        (void *) fxMesa, GL_TRUE);
+   _mesa_init_driver_functions(&functions);
+   ctx = fxMesa->glCtx = _mesa_create_context(fxMesa->glVis, shareCtx,
+                                             &functions, (void *) fxMesa);
    if (!ctx) {
-      errorstr = "_mesa_create_context";
+      str = "_mesa_create_context";
       goto errorhandler;
    }
 
 
-   if (!fxDDInitFxMesaContext( fxMesa )) {
-      errorstr = "fxDDInitFxMesaContext failed"; 
+   if (!fxDDInitFxMesaContext(fxMesa)) {
+      str = "fxDDInitFxMesaContext";
       goto errorhandler;
    }
 
 
-   fxMesa->glBuffer=_mesa_create_framebuffer(fxMesa->glVis,
-                                          GL_FALSE,  /* no software depth */
-                                          fxMesa->glVis->StencilBits > 0,
-                                          fxMesa->glVis->AccumRedBits > 0,
-                                          fxMesa->glVis->AlphaBits > 0 );
+   fxMesa->glBuffer = _mesa_create_framebuffer(fxMesa->glVis,
+                                              GL_FALSE,        /* no software depth */
+                                              stencilSize && !fxMesa->haveHwStencil,
+                                              fxMesa->glVis->accumRedBits > 0,
+                                              alphaSize && !fxMesa->haveHwAlpha);
    if (!fxMesa->glBuffer) {
-      errorstr = "_mesa_create_framebuffer";
+      str = "_mesa_create_framebuffer";
       goto errorhandler;
    }
-  
+
    glbTotNumCtx++;
 
    /* install signal handlers */
 #if defined(__linux__)
    /* Only install if environment var. is not set. */
-   if (fxMesa->glCtx->CatchSignals && !getenv("MESA_FX_NO_SIGNALS")) {
-      signal(SIGINT,cleangraphics_handler);
-      signal(SIGHUP,cleangraphics_handler);
-      signal(SIGPIPE,cleangraphics_handler);
-      signal(SIGFPE,cleangraphics_handler);
-      signal(SIGBUS,cleangraphics_handler);
-      signal(SIGILL,cleangraphics_handler);
-      signal(SIGSEGV,cleangraphics_handler);
-      signal(SIGTERM,cleangraphics_handler);
+   if (!getenv("MESA_FX_NO_SIGNALS")) {
+      signal(SIGINT, cleangraphics_handler);
+      signal(SIGHUP, cleangraphics_handler);
+      signal(SIGPIPE, cleangraphics_handler);
+      signal(SIGFPE, cleangraphics_handler);
+      signal(SIGBUS, cleangraphics_handler);
+      signal(SIGILL, cleangraphics_handler);
+      signal(SIGSEGV, cleangraphics_handler);
+      signal(SIGTERM, cleangraphics_handler);
    }
 #endif
 
-   if (MESA_VERBOSE&VERBOSE_DRIVER) {
-      fprintf(stderr,"fxmesa: fxMesaCreateContext() End\n");
-   }
-
    return fxMesa;
 
- errorhandler:
-   if (fxMesa) {
-      if (fxMesa->glideContext)
-        FX_grSstWinClose(fxMesa->glideContext);
-      fxMesa->glideContext = 0;
-      
-      if (fxMesa->state)  
-        free(fxMesa->state);
-      if (fxMesa->fogTable)
-        free(fxMesa->fogTable);
-      if (fxMesa->glBuffer)
-        _mesa_destroy_framebuffer(fxMesa->glBuffer);
-      if (fxMesa->glVis)
-        _mesa_destroy_visual(fxMesa->glVis);
-      if (fxMesa->glCtx)
-        _mesa_destroy_context(fxMesa->glCtx);
-      free(fxMesa);
-   }
-   
-   if (MESA_VERBOSE&VERBOSE_DRIVER) {
-      fprintf(stderr,"fxmesa: fxMesaCreateContext() End (%s)\n",errorstr);
-   }
-   return NULL;
+errorhandler:
+ if (fxMesa) {
+    if (fxMesa->glideContext) {
+       grSstWinClose(fxMesa->glideContext);
+       fxMesa->glideContext = 0;
+    }
+
+    if (fxMesa->state) {
+       FREE(fxMesa->state);
+    }
+    if (fxMesa->fogTable) {
+       FREE(fxMesa->fogTable);
+    }
+    if (fxMesa->glBuffer) {
+       _mesa_destroy_framebuffer(fxMesa->glBuffer);
+    }
+    if (fxMesa->glVis) {
+       _mesa_destroy_visual(fxMesa->glVis);
+    }
+    if (fxMesa->glCtx) {
+       _mesa_destroy_context(fxMesa->glCtx);
+    }
+    FREE(fxMesa);
+ }
+
+ fprintf(stderr, "fxMesaCreateContext: ERROR: %s\n", str);
+ return NULL;
 }
 
 
 /*
  * Function to set the new window size in the context (mainly for the Voodoo Rush)
  */
-void GLAPIENTRY fxMesaUpdateScreenSize(fxMesaContext fxMesa)
+void GLAPIENTRY
+fxMesaUpdateScreenSize(fxMesaContext fxMesa)
 {
-  fxMesa->width=FX_grSstScreenWidth();
-  fxMesa->height=FX_grSstScreenHeight();
+   fxMesa->width = FX_grSstScreenWidth();
+   fxMesa->height = FX_grSstScreenHeight();
 }
 
 
 /*
  * Destroy the given FX/Mesa context.
  */
-void GLAPIENTRY fxMesaDestroyContext(fxMesaContext fxMesa)
+void GLAPIENTRY
+fxMesaDestroyContext(fxMesaContext fxMesa)
 {
-   if (MESA_VERBOSE&VERBOSE_DRIVER) {
-      fprintf(stderr,"fxmesa: fxMesaDestroyContext()\n");
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxMesaDestroyContext(...)\n");
    }
 
-   if(!fxMesa) 
+   if (!fxMesa)
       return;
 
-   if(fxMesa->verbose) {
-      fprintf(stderr,"Misc Stats:\n");
-      fprintf(stderr,"  # swap buffer: %u\n",fxMesa->stats.swapBuffer);
+   if (fxMesa->verbose) {
+      fprintf(stderr, "Misc Stats:\n");
+      fprintf(stderr, "  # swap buffer: %u\n", fxMesa->stats.swapBuffer);
 
-      if(!fxMesa->stats.swapBuffer)
-        fxMesa->stats.swapBuffer=1;
+      if (!fxMesa->stats.swapBuffer)
+        fxMesa->stats.swapBuffer = 1;
 
-      fprintf(stderr,"Textures Stats:\n");
-      fprintf(stderr,"  Free texture memory on TMU0: %d:\n",fxMesa->freeTexMem[FX_TMU0]);
-      if(fxMesa->haveTwoTMUs)
-        fprintf(stderr,"  Free texture memory on TMU1: %d:\n",fxMesa->freeTexMem[FX_TMU1]);
-      fprintf(stderr,"  # request to TMM to upload a texture objects: %u\n",
+      fprintf(stderr, "Textures Stats:\n");
+      fprintf(stderr, "  Free texture memory on TMU0: %d\n",
+             fxMesa->freeTexMem[FX_TMU0]);
+      if (fxMesa->haveTwoTMUs)
+        fprintf(stderr, "  Free texture memory on TMU1: %d\n",
+                fxMesa->freeTexMem[FX_TMU1]);
+      fprintf(stderr, "  # request to TMM to upload a texture objects: %u\n",
              fxMesa->stats.reqTexUpload);
-      fprintf(stderr,"  # request to TMM to upload a texture objects per swapbuffer: %.2f\n",
-             fxMesa->stats.reqTexUpload/(float)fxMesa->stats.swapBuffer);
-      fprintf(stderr,"  # texture objects uploaded: %u\n",
+      fprintf(stderr,
+             "  # request to TMM to upload a texture objects per swapbuffer: %.2f\n",
+             fxMesa->stats.reqTexUpload / (float) fxMesa->stats.swapBuffer);
+      fprintf(stderr, "  # texture objects uploaded: %u\n",
              fxMesa->stats.texUpload);
-      fprintf(stderr,"  # texture objects uploaded per swapbuffer: %.2f\n",
-             fxMesa->stats.texUpload/(float)fxMesa->stats.swapBuffer);
-      fprintf(stderr,"  # MBs uploaded to texture memory: %.2f\n",
-             fxMesa->stats.memTexUpload/(float)(1<<20));
-      fprintf(stderr,"  # MBs uploaded to texture memory per swapbuffer: %.2f\n",
-             (fxMesa->stats.memTexUpload/(float)fxMesa->stats.swapBuffer)/(float)(1<<20));
+      fprintf(stderr, "  # texture objects uploaded per swapbuffer: %.2f\n",
+             fxMesa->stats.texUpload / (float) fxMesa->stats.swapBuffer);
+      fprintf(stderr, "  # MBs uploaded to texture memory: %.2f\n",
+             fxMesa->stats.memTexUpload / (float) (1 << 20));
+      fprintf(stderr,
+             "  # MBs uploaded to texture memory per swapbuffer: %.2f\n",
+             (fxMesa->stats.memTexUpload /
+              (float) fxMesa->stats.swapBuffer) / (float) (1 << 20));
    }
 
    glbTotNumCtx--;
-   
+
+   if (!glbTotNumCtx && getenv("MESA_FX_INFO")) {
+      GrSstPerfStats_t st;
+
+      FX_grSstPerfStats(&st);
+
+      fprintf(stderr, "Pixels Stats:\n");
+      fprintf(stderr, "  # pixels processed (minus buffer clears): %u\n",
+              (unsigned) st.pixelsIn);
+      fprintf(stderr, "  # pixels not drawn due to chroma key test failure: %u\n",
+              (unsigned) st.chromaFail);
+      fprintf(stderr, "  # pixels not drawn due to depth test failure: %u\n",
+              (unsigned) st.zFuncFail);
+      fprintf(stderr,
+              "  # pixels not drawn due to alpha test failure: %u\n",
+              (unsigned) st.aFuncFail);
+      fprintf(stderr, "  # pixels drawn (including buffer clears and LFB writes): %u\n",
+              (unsigned) st.pixelsOut);
+   }
+
+   /* [dBorca]
+    * close the hardware first, so we can debug
+    * atexit problems (memory leaks, etc).
+    * NB: fxDDDestroyFxMesaContext must be called
+    * before _mesa_destroy_context; which must be
+    * called before fxTMClose!
+    */
+   grSstWinClose(fxMesa->glideContext);
+   fxCloseHardware();
+
    fxDDDestroyFxMesaContext(fxMesa);
    _mesa_destroy_visual(fxMesa->glVis);
    _mesa_destroy_context(fxMesa->glCtx);
    _mesa_destroy_framebuffer(fxMesa->glBuffer);
+   fxTMClose(fxMesa);
 
-   fxCloseHardware();
-   FX_grSstWinClose(fxMesa->glideContext);
-
-   free(fxMesa);
+   FREE(fxMesa);
 
-   if(fxMesa==fxMesaCurrentCtx)
-      fxMesaCurrentCtx=NULL;
+   if (fxMesa == fxMesaCurrentCtx)
+      fxMesaCurrentCtx = NULL;
 }
 
 
 /*
  * Make the specified FX/Mesa context the current one.
  */
-void GLAPIENTRY fxMesaMakeCurrent(fxMesaContext fxMesa)
+void GLAPIENTRY
+fxMesaMakeCurrent(fxMesaContext fxMesa)
 {
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) Start\n");
-  }
+   if (!fxMesa) {
+      _mesa_make_current(NULL, NULL);
+      fxMesaCurrentCtx = NULL;
 
-  if(!fxMesa) {
-    _mesa_make_current(NULL,NULL);
-    fxMesaCurrentCtx=NULL;
-
-    if (MESA_VERBOSE&VERBOSE_DRIVER) {
-      fprintf(stderr,"fxmesa: fxMesaMakeCurrent(NULL) End\n");
-    }
-
-    return;
-  }
-
-  /* if this context is already the current one, we can return early */
-  if (fxMesaCurrentCtx == fxMesa
-      && fxMesaCurrentCtx->glCtx == _mesa_get_current_context()) {
-     if (MESA_VERBOSE&VERBOSE_DRIVER) {
-        fprintf(stderr,"fxmesa: fxMesaMakeCurrent(fxMesaCurrentCtx==fxMesa) End\n");
-    }
+      if (TDFX_DEBUG & VERBOSE_DRIVER) {
+        fprintf(stderr, "fxMesaMakeCurrent(NULL)\n");
+      }
 
-    return;
-  }
+      return;
+   }
 
-  if(fxMesaCurrentCtx)
-    grGlideGetState((GrState*)fxMesaCurrentCtx->state);
+   /* if this context is already the current one, we can return early */
+   if (fxMesaCurrentCtx == fxMesa
+       && fxMesaCurrentCtx->glCtx == _mesa_get_current_context()) {
+      if (TDFX_DEBUG & VERBOSE_DRIVER) {
+        fprintf(stderr, "fxMesaMakeCurrent(NOP)\n");
+      }
 
-  fxMesaCurrentCtx=fxMesa;
+      return;
+   }
 
-  grSstSelect(fxMesa->board);
-  grGlideSetState((GrState*)fxMesa->state);
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxMesaMakeCurrent(...)\n");
+   }
 
-  _mesa_make_current(fxMesa->glCtx,fxMesa->glBuffer);
+   if (fxMesaCurrentCtx)
+      grGlideGetState((GrState *) fxMesaCurrentCtx->state);
 
-  fxSetupDDPointers(fxMesa->glCtx);
+   fxMesaCurrentCtx = fxMesa;
 
-  /* The first time we call MakeCurrent we set the initial viewport size */
-  if(fxMesa->glCtx->Viewport.Width==0)
-    gl_Viewport(fxMesa->glCtx,0,0,fxMesa->width,fxMesa->height);
+   grSstSelect(fxMesa->board);
+   grGlideSetState((GrState *) fxMesa->state);
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) End\n");
-  }
-}
+   _mesa_make_current(fxMesa->glCtx, fxMesa->glBuffer);
 
+   fxSetupDDPointers(fxMesa->glCtx);
 
-#if 0
-static void QueryCounters(void)
-{
-   static GLuint prevPassed = 0;
-   static GLuint prevFailed = 0;
-   GLuint failed, passed;
-   GrSstPerfStats_t st;
-
-   FX_grSstPerfStats(&st);
-   failed = st.zFuncFail - st.aFuncFail - st.chromaFail;
-   passed = st.pixelsIn - failed;
-   printf("failed: %d  passed: %d\n", failed - prevFailed, passed - prevPassed);
-
-   prevPassed = passed;
-   prevFailed = failed;
+   /* The first time we call MakeCurrent we set the initial viewport size */
+   if (fxMesa->glCtx->Viewport.Width == 0)
+      _mesa_set_viewport(fxMesa->glCtx, 0, 0, fxMesa->width, fxMesa->height);
 }
-#endif
 
 
 /*
  * Swap front/back buffers for current context if double buffered.
  */
-void GLAPIENTRY fxMesaSwapBuffers(void)
+void GLAPIENTRY
+fxMesaSwapBuffers(void)
 {
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: ------------------------------- fxMesaSwapBuffers() -------------------------------\n");
-  }
-
-  if(fxMesaCurrentCtx) {
-     _mesa_swapbuffers( fxMesaCurrentCtx->glCtx );
-
-    if(fxMesaCurrentCtx->haveDoubleBuffer) {
-
-      grBufferSwap(fxMesaCurrentCtx->swapInterval);
-
-      /*
-       * Don't allow swap buffer commands to build up!
-       */
-      while(FX_grGetInteger(FX_PENDING_BUFFERSWAPS)>fxMesaCurrentCtx->maxPendingSwapBuffers)
-        /* The driver is able to sleep when waiting for the completation
-           of multiple swapbuffer operations instead of wasting
-           CPU time (NOTE: you must uncomment the following line in the
-           in order to enable this option) */
-        /* usleep(10000); */
-        ;
-
-      fxMesaCurrentCtx->stats.swapBuffer++;
-    }
-  }
-}
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxMesaSwapBuffers()\n");
+   }
 
+   if (fxMesaCurrentCtx) {
+      _mesa_notifySwapBuffers(fxMesaCurrentCtx->glCtx);
 
-/*
- * Query 3Dfx hardware presence/kind
- */
-int GLAPIENTRY fxQueryHardware(void)
-{
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxQueryHardware() Start\n");
-  }
+      if (fxMesaCurrentCtx->haveDoubleBuffer) {
 
-  if (!glbGlideInitialized) {
-    grGlideInit();
-    if (FX_grSstQueryHardware(&glbHWConfig)) {
-      grSstSelect(glbCurrentBoard);
-      glb3DfxPresent = 1;
-
-      if (getenv("MESA_FX_INFO")) {
-        char buf[80];
-                        
-        FX_grGlideGetVersion(buf);
-        fprintf(stderr, "Voodoo Using Glide V%s\n", buf);
-        fprintf(stderr, "Voodoo Number of boards: %d\n", glbHWConfig.num_sst);
-
-        if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) {
-          GrVoodooConfig_t *voodoo;
-          voodoo = &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig;
-
-          fprintf(stderr, "Voodoo Framebuffer RAM: %d\n",
-            voodoo->sliDetect ? (voodoo->fbRam*2) : voodoo->fbRam);
-          fprintf(stderr, "Voodoo Number of TMUs: %d\n", voodoo->nTexelfx);
-          fprintf(stderr, "Voodoo fbRam: %d\n", voodoo->fbRam);
-          fprintf(stderr, "Voodoo fbiRev: %d\n", voodoo->fbiRev);
-
-          fprintf(stderr,"Voodoo SLI detected: %d\n", voodoo->sliDetect);
-        }
-        else if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_SST96) {
-          GrSst96Config_t *sst96;
-          sst96 = &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config;
-          fprintf(stderr, "Voodoo Framebuffer RAM: %d\n", sst96->fbRam);
-          fprintf(stderr, "Voodoo Number of TMUs: %d\n", sst96->nTexelfx);
-        }
+        grBufferSwap(fxMesaCurrentCtx->swapInterval);
 
-      }
-    }
-    else {
-      glb3DfxPresent = 0;
-    }
-
-    glbGlideInitialized = 1;
-
-#if defined(__WIN32__)
-    onexit((_onexit_t)cleangraphics);
-#elif defined(__linux__)
-    /* Only register handler if environment variable is not defined. */
-    if (!getenv("MESA_FX_NO_SIGNALS")) {
-       atexit(cleangraphics);
-    }
+#if 0
+        /*
+         * Don't allow swap buffer commands to build up!
+         */
+        while (FX_grGetInteger(GR_PENDING_BUFFERSWAPS) >
+               fxMesaCurrentCtx->maxPendingSwapBuffers)
+           /* The driver is able to sleep when waiting for the completation
+              of multiple swapbuffer operations instead of wasting
+              CPU time (NOTE: you must uncomment the following line in the
+              in order to enable this option) */
+           /* usleep(10000); */
+           ;
 #endif
-  }
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxQueryHardware() End (voodooo)\n");
-  }
-
-  return glbHWConfig.SSTs[glbCurrentBoard].type;
+        fxMesaCurrentCtx->stats.swapBuffer++;
+      }
+   }
 }
 
 
 /*
  * Shutdown Glide library
  */
-void GLAPIENTRY fxCloseHardware(void)
+void GLAPIENTRY
+fxCloseHardware(void)
 {
-  if (glbGlideInitialized) {
-    if (getenv("MESA_FX_INFO")) {
-      GrSstPerfStats_t          st;
-
-      FX_grSstPerfStats(&st);
-      fprintf(stderr,"Pixels Stats:\n");
-      fprintf(stderr,"  # pixels processed (minus buffer clears): %u\n",(unsigned)st.pixelsIn);
-      fprintf(stderr,"  # pixels not drawn due to chroma key test failure: %u\n",(unsigned)st.chromaFail);
-      fprintf(stderr,"  # pixels not drawn due to depth test failure: %u\n",(unsigned)st.zFuncFail);
-      fprintf(stderr,"  # pixels not drawn due to alpha test failure: %u\n",(unsigned)st.aFuncFail);
-      fprintf(stderr,"  # pixels drawn (including buffer clears and LFB writes): %u\n",(unsigned)st.pixelsOut);
-    }
-
-    if (glbTotNumCtx == 0) {
-      grGlideShutdown();
-      glbGlideInitialized = 0;
-    }
-  }
+   if (glbGlideInitialized) {
+      if (glbTotNumCtx == 0) {
+        grGlideShutdown();
+        glbGlideInitialized = 0;
+      }
+   }
 }
 
 
@@ -834,9 +949,10 @@ void GLAPIENTRY fxCloseHardware(void)
  * Need this to provide at least one external definition.
  */
 extern int gl_fx_dummy_function_api(void);
-int gl_fx_dummy_function_api(void)
+int
+gl_fx_dummy_function_api(void)
 {
-  return 0;
+   return 0;
 }
 
-#endif  /* FX */
+#endif /* FX */