Rename the various function types in t_context.h to include a tnl_ prefix.
[mesa.git] / src / mesa / drivers / glide / fxapi.c
index ca5618810372bce04607b3a0c57cdb5468c7ed4c..0dccdc2093bd61cebd0477fca97d4e140f09efbe 100644 (file)
@@ -1,10 +1,8 @@
-/* -*- mode: C; tab-width:8;  -*- */
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
+ * Version:  4.0
  *
- * Copyright (C) 1999  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 - 3Dfx VooDoo/Mesa interface */
 
-
-/********************************************************************
- *
- * Function names:
- *  fxMesa....     (The driver API)
- *  fxDD....       (Mesa device driver functions)
- *  fxTM....       (Texture manager functions)
- *  fxSetup....    (Voodoo units setup functions)
- *  fx....         (Internal driver functions)
- *
- * Data type names:
- *  fxMesa....     (Public driver data types)
- *  tfx....        (Private driver data types)
- *
- ********************************************************************
- *
- * V0.30 - David Bucciarelli (davibu@tin.it) Humanware s.r.l.
- *         - introduced a new MESA_GLX_FX related behavior
- *         - the Glide fog table was built in a wrong way (using
- *           gu* Glide function). Added the code for building the
- *           table following the OpenGL specs. Thanks to Steve Baker
- *           for highlighting the problem.
- *         - fixed few problems in my and Keith's fxDDClear code
- *         - merged my code with the Keith's one
- *         - used the new BlendFunc Mesa device driver function 
- *         - used the new AlphaFunc Mesa device driver function 
- *         - used the new Enable Mesa device driver function 
- *         - fixed a bug related to fog in the Mesa core. Fog
- *           were applied two times: at vertex level and at fragment
- *           level (thanks to Steve Baker for reporting the problem)
- *         - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE) now works
- *           (thanks to Jiri Pop for reporting the problem)
- *         - the driver works fine with OpenGL Unreal
- *         - fixed a bug in the Mesa core clipping code (related
- *           to the q texture coordinate)
- *         - introduced the support for the q texture coordinate
- *
- *         Keith Whitwell (keithw@cableinet.co.uk)
- *         - optimized the driver and written all the new code
- *           required by the new Mesa-3.1 device driver API
- *           and by the new Mesa-3.1 core changes
- *         - written the cva support and many other stuff
- *
- *         Brian Paul (brian_paul@avid.com) Avid Technology
- *         - fixed display list share bug for MESA_GLX_FX = window/fullscreen
- *         - fixed glClear/gl...Mask related problem
- *
- *         Bert Schoenwaelder (bert@prinz-atm.CS.Uni-Magdeburg.De)
- *         - the driver is now able to sleep when waiting for the completation
- *           of multiple swapbuffer operations instead of wasting
- *           CPU time (NOTE: you must uncomment the lines in the
- *           fxMesaSwapBuffers function in order to enable this option)
- *
- *         Eero Pajarre (epajarre@koti.tpo.fi)
- *         - enabled the macro FLOAT_COLOR_TO_UBYTE_COLOR under
- *           windows
- *         - written an asm x86 optimized float->integer conversions
- *           for windows
- *
- *         Theodore Jump (tjump@cais.com)
- *         - fixed a small problem in the __wglMonitor function of the
- *           wgl emulator
- *         - written the in-window-rendering hack support for windows
- *           and Vooodoo1/2 cards
- *
- * V0.29 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - included in Mesa-3.0
- *         - now glGetString(GL_RENDERER) returns more information
- *           about the hardware configuration: "Mesa Glide <version>
- *           <Voodoo_Graphics|Voodoo_Rush|UNKNOWN> <num> CARD/<num> FB/
- *           <num> TM/<num> TMU/<NOSLI|SLI>"
- *           where: <num> CARD is the card used for the current context,
- *           <num> FB is the number of MB for the framebuffer,
- *           <num> TM is the number of MB for the texture memory,
- *           <num> TMU is the number of TMU. You can try to run
- *           Mesa/demos/glinfo in order to have an example of the
- *           output
- *         - fixed a problem of the WGL emulator with the
- *           OpenGL Optimizer 1.1 (thanks to Erwin Coumans for
- *           the bug report)
- *         - fixed some bug in the fxwgl.c code (thanks to  
- *           Peter Pettersson for a patch and a bug report)
- *
- *         Theodore Jump (tjump@cais.com)
- *         - written the SST_DUALHEAD support in the WGL emulator
- *
- *         Daryll Strauss (daryll@harlot.rb.ca.us)
- *         - fixed the Voodoo Rush support for the in window rendering
- *
- * V0.28 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - the only supported multitexture functions are GL_MODULATE
- *           for texture set 0 and GL_MODULATE for texture set 1. In
- *           all other cases, the driver falls back to pure software
- *           rendering
- *         - written the support for the new  GL_EXT_multitexture
- *         - written the DD_MAX_TEXTURE_COORD_SETS support in the
- *           fxDDGetParameteri() function
- *         - the driver falls back to pure software rendering when
- *           texture mapping function is GL_BLEND
- *
- * V0.27 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - inluded in the Mesa-3.0beta5
- *         - written a smal extension (GL_FXMESA_global_texture_lod_bias) in
- *           order to expose the LOD bias related Glide function
- *         - fixed a bug fxDDWriteMonoRGBAPixels()
- *         - the driver is now able to fallback to software rendering in
- *           any case not directly supported by the hardware
- *         - written the support for enabling/disabling dithering
- *         - the in-window-rendering hack now works with any X11 screen
- *           depth
- *         - fixed a problem related to color/depth/alpha buffer clears
- *         - fixed a problem when clearing buffer for a context with the
- *           alpha buffer
- *         - fixed a problem in the fxTMReloadSubMipMapLevel() function,
- *           I have forget a "break;" (thanks to Joe Waters for the bug report)
- *         - fixed a problem in the color format for the in window
- *           rendering hack
- *         - written the fxDDReadRGBAPixels function
- *         - written the fxDDDepthTestPixelsGeneric function
- *         - written the fxDDDepthTestSpanGeneric function
- *         - written the fxDDWriteMonoRGBAPixels function
- *         - written the fxDDWriteRGBAPixels function
- *         - removed the multitexture emulation code for Voodoo board
- *         with only one TMU
- *
- *         Chris Prince <cprince@cs.washington.edu>
- *         - fixed a new bug in the wglUseFontBitmaps code
- *
- *         Ralf Knoesel (rknoesel@Stormfront.com)
- *         - fixed a bug in the wglUseFontBitmaps code
- *
- *         Rune Hasvold (runeh@ifi.uio.no)
- *         - fixed a problem related to the aux usage in the fxBestResolution
- *           function
- *         - fixed the order of pixel formats in the WGL emulator
- *
- *         Fredrik Hubinette (hubbe@hubbe.net)
- *         - the driver shutdown the Glide for most common signals
- *
- * V0.26 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - included in the Mesa-3.0beta4
- *         - fixed a problem related to a my optimization for the Rune's
- *           pixel-span optimization
- *         - fixed a problem related to fxDDSetNearFar() and ctx->ProjectionMatrixType
- *           (thanks to Ben "Ctrl-Alt-Delete" and the Raul Alonso's ssystem)
- *         - fixed a small bug in the Rune's pixel-span optimization
- *         - fixed a problem with GL_CCW (thanks to Curt Olson for and example
- *           of the problem)
- *         - grVertex setup code is now ready for the internal thread support
- *         - fixed a no used optimization with clipped vertices in
- *           grVertex setup code
- *         - fixed a problem in the GL_LIGHT_MODEL_TWO_SIDE support (thanks
- *           to Patrick H. Madden for a complete example of the bug)
- *
- *         Rune Hasvold (runeh@ifi.uio.no)
- *         - highly optimized the driver functions for writing pixel
- *           span (2-3 times faster !)
- *
- *         Axel W. Volley (volley@acm.org) Krauss-Maffei Wehrtechnik
- *         - written the fxDDReadDepthSpanFloat() and fxDDReadDepthSpanInt()
- *           functions
- *
- * V0.25 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - fixed a problem with Voodoo boards with only one TMU
- *         - fixed a bug in the fxMesaCreateContext()
- *         - now the GL_FRONT_AND_BACK works fine also with
- *           the alpha buffer and/or antialiasing
- *         - written the support for GL_FRONT_AND_BACK drawing but
- *           it doesn't works with the alpha buffer and/or antialiasing
- *         - fixed some bug in the Mesa core for glCopyTexSubImage
- *           and glCopyTexImage functions (thanks to Mike Connell
- *           for an example of the problem)
- *         - make some small optimizations in the Mesa core in order
- *           to save same driver call and state change for not very
- *           well written applications
- *         - introduced the NEW_DRVSTATE and make other optimizations
- *           for minimizing state changes
- *         - made a lot of optimizations in order to minimize state
- *           changes
- *         - it isn't more possible to create a context with the
- *           depth buffer and the stancil buffer (it isn't yet supported)
- *         - now the partial support for the Multitexture extension
- *           works with Quake2 for windows
- *         - vertex snap is not longer used for the Voodoo2 (FX_V2
- *           must be defined)
- *         - done a lot of cleanup in the fxsetup.c file
- *         - now the partial support for the Multitexture extension
- *           works with GLQuake for windows
- *
- *         Dieter Nuetzel (nuetzel@kogs.informatik.uni-hamburg.de) University of Hamburg
- *         - fixed a problem in the asm code for Linux of the fxvsetup.c file
- *           highlighted by the binutils-2.8.1.0.29. 'fildw' asm instruction
- *           changed in 'fild'
- *
- *         Kevin Hester (kevinh@glassworks.net)
- *         - written the wglUseFontBitmaps() function in the WGL emulator
- *
- * V0.24 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - now the drive always uses per fragment fog
- *         - written a small optimization in the points drawing function
- *         - written the support for trilinear filtering with 2 TMUs
- *         - written the first partial support for the Multitexture extension.
- *           This task is quite hard because the color combine units work after
- *           the two texture combine units and not before as required by the 
- *           Multitexture extension
- *         - written a workaround in fxBestResolution() in order to solve a
- *           problem with bzflag (it asks for 1x1 window !)
- *         - changed the fxBestResolution() behavior. It now returns the larger
- *           screen resolution supported by the hardware (instead of 640x480)
- *           when it is unable to find an appropriate resolution that is large
- *           enough for the requested size 
- *         - the driver is now able to use also the texture memory attached to
- *           second TMU
- *         - the texture memory manager is now able to work with two TMUs and
- *           store texture maps in the memory attached to TMU0, TMU1 or to split
- *           the mimpmap levels across TMUs in order to support trilinear filtering
- *         - I have bought a Voodoo2 board !
- *         - the amount of frambuffer ram is now doubled when an SLI configuration
- *           is detected
- *         - solved a problem related to the fxDDTexParam() and fxTexInvalidate()
- *           functions (thanks to Rune Hasvold for highlighting the problem)
- *         - done some cleanup in the fxvsetup.c file, written
- *           the FXVSETUP_FUNC macro
- *         - done a lot of cleanup in data types and field names
- *
- *         Rune Hasvold (runeh@ifi.uio.no)
- *         - written the support for a right management of the auxiliary buffer.
- *           You can now use an 800x600 screen without the depth and alpha
- *           buffer
- *         - written the support for a new pixel format (without the depth
- *           and alpha buffer) in the WGL emulator
- *         - fixed a bug in the window version of the GLUT (it was ever asking
- *           for depth buffer)
- *
- * V0.23 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - included in the Mesa-3.0beta2 release
- *         - written the support for the OpenGL 1.2 GL_TEXTURE_BASE_LEVEL
- *           and GL_TEXTURE_MAX_LEVEL
- *         - rewritten several functions for a more clean support of texture
- *           mapping and in order to solve some bug
- *         - the accumulation buffer works (it is  bit slow beacuase it requires
- *           to read/write from/to the Voodoo frame buffer but it works)
- *         - fixed a bug in the fxDDReadRGBASpan driver function (the R and
- *           B channels were read in the wrong order). Thanks to Jason Heym
- *           for highlighting the problem
- *         - written the support for multiple contexts on multiple boards.
- *           you can now use the Mesa/Voodoo with multiple Voodoo Graphics
- *           boards (for example with multiple screens or an HMD)
- *         - the fxBestResolution() now check all available resolutions
- *           and it is able to check the amount of framebuffer memory
- *           before return a resolution
- *         - modified the GLX/X11 driver in order to support all the
- *           resolution available
- *         - changed all function names. They should be now a bit more
- *           readable
- *         - written the Glide grVertex setup code for two TMU or
- *           for Multitexture support with emulationa dn one TMU
- *         - written the support for the new Mesa driver
- *           function GetParametri
- *         - small optimization/clean up in the texbind() function
- *         - fixed a FPU precision problem for glOrtho and texture
- *           mapping (thanks to Antti Juhani Huovilainen for an example
- *           of the problem)
- *         - written some small SGI OpenGL emulation code for the wgl,
- *           the OpenGL Optimizer and Cosmo3D work fine under windows !
- *         - moved the point/line/triangle/quad support in the fxmesa7.c
- *         - fixed a bug in the clear_color_depth() (thanks to Henk Kok
- *           for an example of the problem)
- *         - written a small workaround for Linux GLQuake, it asks
- *           for the alpha buffer and the depth buffer at the some time
- *           (but it never uses the alpha buffer)
- *         - checked the antialiasing points, lines and polygons support.
- *           It works fine
- *         - written the support for standard OpenGL antialiasing using
- *           blending. Lines support works fine (tested with BZflag)
- *           while I have still to check the polygons and points support
- *         - written the support for the alpha buffer. The driver is now
- *           able to use the Voodoo auxiliary buffer as an alpha buffer
- *           instead of a depth buffer. Also all the OpenGL blending
- *           modes are now supported. But you can't request a context
- *           with an alpha buffer AND a depth buffer at the some time
- *           (this is an hardware limitation)
- *         - written the support for switching between the fullscreen
- *           rendering and the in-window-rendering hack on the fly
- *
- *         Rune Hasvold (runeh@ifi.uio.no)
- *         - fixed a bug in the texparam() function
- *
- *         Brian Paul (brianp@elastic.avid.com) Avid Technology
- *         - sources accomodated for the new Mesa 3.0beta1
- *
- * V0.22 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - included with some v0.23 bug fix in the final release
- *           of the Mesa-2.6
- *         - written the support for the MESA_WGL_FX env. var. but
- *           not tested because I have only Voodoo Graphics boards
- *         - fixed a bug in the backface culling code
- *           (thanks to David Farrell for an example of the problem)
- *         - fixed the "Quake2 elevator" bug
- *         - GL_POLYGONS with 3/4 vertices are now drawn as
- *           GL_TRIANLGES/GL_QUADS (a small optimization for GLQuake)
- *         - fixed a bug in fxmesa6.h for GL_LINE_LOOP
- *         - fixed a NearFarStack bug in the Mesa when applications
- *           directly call glLoadMatrix to load a projection matrix 
- *         - done some cleanup in the fxmesa2.c file
- *         - the driver no longer translates the texture maps
- *           when the Mesa internal format and the Voodoo
- *           format are the some (usefull for 1 byte texture maps
- *           where the driver can directly use the Mesa texture
- *           map). Also the amount of used memory is halfed
- *         - fixed a bug for GL_DECAL and GL_RGBA
- *         - fixed a bug in the clear_color_depth()
- *         - tested the v0.22 with the Mesa-2.6beta2. Impressive
- *           performances improvement thanks to the new Josh's
- *           asm code (+10fps in the isosurf demo, +5fps in GLQuake
- *           TIMEREFRESH)
- *         - written a optimized version of the RenderVB Mesa driver
- *           function. The Voodoo driver is now able to upload polygons
- *           in the most common cases at a very good speed. Good
- *           performance improvement for large set of small polygons
- *         - optimized the asm code for setting up the color information
- *           in the Glide grVertex structure
- *         - fixed a bug in the fxmesa2.c asm code (the ClipMask[]
- *           wasn't working)
- *
- *         Josh Vanderhoof (joshv@planet.net)
- *         - removed the flush() function because it isn't required
- *         - limited the maximum number of swapbuffers in the Voodoo
- *           commands FIFO (controlled by the env. var. MESA_FX_SWAP_PENDING)
- *
- *         Holger Kleemiss (holger.kleemiss@metronet.de) STN Atlas Elektronik GmbH
- *         - applied some patch for the Voodoo Rush
- *
- * V0.21 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - the driver is now able to take advantage of the ClipMask[],
- *           ClipOrMask and ClipAndMask information also under Windows
- *         - introduced a new function in the Mesa driver interface
- *           ClearColorAndDepth(). Now the glClear() function is
- *           2 times faster (!) when you have to clear the color buffer
- *           and the depth buffer at some time
- *         - written the first version of the fxRenderVB() driver
- *           function
- *         - optimized the glTexImage() path
- *         - removed the fxMesaTextureUsePalette() support
- *         - fixed a bug in the points support (thanks to David Farrell
- *           for an example of the problem)
- *         - written the optimized path for glSubTexImage(),
- *           introduced a new function in the Mesa driver interface
- *           TexSubImage(...)
- *         - fixed a bug for glColorMask and glDepthMask
- *         - the wbuffer is not more used. The Voodoo driver uses
- *           a standard 16bit zbuffer in all cases. It is more consistent
- *           and now GLQuake and GLQuake2test work also with a GL_ZTRICK 0
- *         - the driver is now able to take advantage of the ClipMask[],
- *           ClipOrMask and ClipAndMask information (under Linux);
- *         - rewritten the setup_fx_units() function, now the texture
- *           mapping support is compliant to the OpenGL specs (GL_BLEND
- *           support is still missing). The LinuxGLQuake console correctly
- *           fade in/out and transparent water of GLQuake2test works fine
- *         - written the support for the env. var. FX_GLIDE_SWAPINTERVAL
- *         - found a bug in the Mesa core. There is a roundup problem for
- *           color values out of the [0.0,1.0] range
- *
- *         Wonko <matt@khm.de>
- *         - fixed a Voodoo Rush related problem in the fxwgl.c
- *
- *         Daryll Strauss <daryll@harlot.rb.ca.us>
- *         - written the scissor test support
- *
- * V0.20 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - written the closetmmanger() function in order to free all the memory
- *           allocated by the Texture Memory Manager (it will be useful
- *           when the support for multiple contexts/boards will be ready)
- *         - now the Voodoo driver runs without printing any information,
- *           define the env. var. MESA_FX_INFO if you want to read some
- *           information about the hardware and some statistic
- *         - written a small workaround for the "GLQuake multiplayer white box bug"
- *           in the setup_fx_units() funxtions. I'm already rewriting
- *           this function because it is the source of nearly all the current
- *           Voodoo driver problems
- *         - fixed the GLQuake texture misalignment problem (the texture
- *           coordinates must be scaled between 0.0 and 256.0 and not
- *           between 0.0 and 255.0)
- *         - written the support for the GL_EXT_shared_texture_palette
- *         - some small change for supporting the automatic building of the
- *           OpenGL32.dll under the Windows platform
- *         - the redefinition of a mipmap level is now a LOT faster. This path
- *           is used by GLQuake for dynamic lighting with some call to glTexSubImage2D()
- *         - the texture memory is now managed a set of 2MB blocks so
- *           texture maps can't be allocated on a 2MB boundary. The new Pure3D
- *           needs this kind of support (and probably any other Voodoo Graphics
- *           board with more than 2MB of texture memory)
- *
- *         Brian Paul (brianp@elastic.avid.com) Avid Technology
- *         - added write_monocolor_span(), fixed bug in write_color_span()
- *         - added test for stenciling in choosepoint/line/triangle functions
- *
- *         Joe Waters (falc@attila.aegistech.com) Aegis
- *         - written the support for the env. var. SST_SCREENREFRESH
- *
- * V0.19 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - written the 3Dfx Global Palette extension for GLQuake
- *         - written the support for the GL_EXT_paletted_texture (it works only with GL_RGBA
- *           palettes and the alpha value is ignored ... this is a limitation of the
- *           the current Glide version and Voodoo hardware)
- *         - fixed the amount of memory allocated for 8bit textures
- *         - merged the under construction v0.19 driver with the Mesa 2.5
- *         - finally written the support for deleting textures
- *         - introduced a new powerful texture memory manager: the texture memory
- *           is used as a cache of the set of all defined texture maps. You can
- *           now define several MB of texture maps also with a 2MB of texture memory
- *           (the texture memory manager will do automatically all the swap out/swap in
- *           work). The new texture memory manager has also
- *           solved a lot of other bugs/no specs compliance/problems
- *           related to the texture memory usage. The texture
- *           manager code is inside the new fxmesa3.c file
- *         - broken the fxmesa.c file in two files (fxmesa1.c and fxmesa2.c)
- *           and done some code cleanup
- *         - now is possible to redefine texture mipmap levels already defined
- *         - fixed a problem with the amount of texture memory allocated for textures
- *           with not all mipmap levels defined
- *         - fixed a small problem with single buffer rendering
- *
- *         Brian Paul (brianp@elastic.avid.com) Avid Technology
- *         - read/write_color_span() now use front/back buffer correctly
- *         - create GLvisual with 5,6,5 bits per pixel, not 8,8,8
- *         - removed a few ^M characters from fxmesa2.c file
- *
- * V0.18 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - the Mesa-2.4beta3 is finally using the driver quads support (the
- *           previous Mesa versions have never taken any advantage from the quads support !)
- *         - tested with the Glide 2.4 for Win
- *         - ported all asm code to Linux
- *         - ported the v0.18 to Linux (without asm code)
- *         - back to Linux !!!
- *         - optimized the SETUP macro (no more vertex snap for points and lines)
- *         - optimized the SETUP macro (added one argument)
- *         - the Mesa/Voodoo is now 20/30% for points, lines and small triangles !
- *         - performance improvement setting VBSIZE to 72 
- *         - the GrVertex texture code is now written in asm
- *         - the GrVertex zbuffer code is now written in asm
- *         - the GrVertex wbuffer code is now written in asm
- *         - the GrVertex gouraud code is now written in asm
- *         - the GrVertex snap code is now written in asm
- *         - changed the 8bit compressed texture maps in 8bit palette texture maps
- *           support (it has the some advantage of compressed texture maps without the
- *           problem of a fixed NCC table for all mipmap levels)
- *         - written the support for 8bit compressed texture maps (but texture maps with
- *           more than one mipmap level aren't working fine)
- *         - finnaly everthing is working fine in MesaQuake !
- *         - fixed a bug in the computation of texture mapping coordinates (I have found
- *           the bug thanks to MesaQuake !)
- *         - written the GL_REPLACE support (mainly for MesaQuake)
- *         - written the support for textures with not all mipmap levels defined
- *         - rewritten all the Texture memory stuff
- *         - written the MesaQuake support (define MESAQUAKE)
- *         - working with a ZBuffer if glOrtho or not int the default glDepthRange,
- *           otherwise working with the WBuffer
- *         written the glDepthRange support
- *
- *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
- *         - written the fxCloseHardware() and the fxQuaryHardware() (mainly
- *           for the VoodooWGL emulator)
- *
- *         Brian Paul (brianp@elastic.avid.com) Avid Technology
- *         - implemented read/write_color_span() so glRead/DrawPixels() works
- *         - now needs Glide 2.3 or later.  Removed GLIDE_FULL_SCREEN and call to grSstOpen()
- *
- * V0.17 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - optimized the bitmap support (66% faster)
- *         - tested with the Mesa 2.3beta2
- *
- *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
- *         - solved a problem with the drawbitmap() and the Voodoo Rush
- *           (GR_ORIGIN_LOWER_LEFT did not work with the Stingray)
- *
- *         Brian Paul (brianp@elastic.avid.com) Avid Technology
- *         - linux stuff
- *         - general code clean-up
- *         - added attribList parameter to fxMesaCreateContext()
- *         - single buffering works now
- *         - VB colors are now GLubytes, removed ColorShift stuff
- *
- *         Paul Metzger
- *         - linux stuff
- *
- * V0.16 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - written the quadfunc support (no performance improvement)
- *         - written the support for the new Mesa 2.3beta1 driver interface (Wow ! It is faaaster)
- *         - rewritten the glBitmap support for the Glide 2.3 (~35% slower !)
- *         - written the glBitmap support for the most common case (fonts)
- *
- *         Jack Palevich
- *         - Glide 2.3 porting
- *
- *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
- *         - extended the fxMesaCreateContext() and fxMesaCreateBestContext()
- *           functions in order to support also the Voodoo Rush
- *         - tested with the Hercules Stingray 128/3D (The rendering in a window works !)
- *
- * V0.15 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - written the GL_LUMINANCE_ALPHA support
- *         - written the GL_ALPHA support
- *         - written the GL_LUMINANCE support
- *         - now SETUP correctly set color for mono color sequences
- *         - written the 9x1,10x1,...,1x9,1x10,... texture map ratio support
- *         - written the no square texture map support
- *         - the fog table is no more rebuilt inside setup_fx_units() each time
- *
- *         Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation
- *         - written (not yet finished: no texture mapping) support for glOrtho
- *         - some change to setup functions
- *         - the fog support is now fully compatible with the standard OpenGL
- *         - rewritten several parts of the driver in order to take
- *           advantage of meshes (40% faster !!!)
- *
- * V0.14 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - now glAlphaFunc() works
- *         - now glDepthMask() works
- *         - solved a mipmap problem when using more than one texture
- *         - moved ti, texid and wscale inside the fxMesaContext (now we can
- *           easy support more ctx and more boards)
- *         - the management of the fxMesaContext was completly broken !
- *         - solved several problems about Alpha and texture Alpha
- *         - 4 (RGBA) texture channels supported
- *         - setting the default color to white
- *
- *         Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation
- *         - small change to fxMesaCreateContext() and fxMesaMakeCurrent()
- *         - written the fog support
- *         - setting the default clear color to black
- *         - written cleangraphics() for the onexit() function
- *         - written fxMesaCreateBestContext()
- *
- * V0.13 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - now glBlendFunc() works for all glBlendFunc without DST_ALPHA
- *           (because the alpha buffer is not yet implemented) 
- *         - now fxMesaCreateContext() accept resolution and refresh rate
- *         - fixed a bug for texture mapping: the w (alias z) must be set
- *           also without depth buffer
- *         - fixed a bug for texture image with width!=256
- *         - written texparam()
- *         - written all point, line and triangle functions for all possible supported
- *           contexts and the driver is slight faster with points, lines and small triangles
- *         - fixed a small bug in fx/fxmesa.h (glOrtho)
- *
- * V0.12 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - glDepthFunc supported
- *         - introduced a trick to discover the far plane distance
- *           (see fxMesaSetFar and fx/fxmesa.h)
- *         - now the wbuffer works with homogeneous coordinate (and it
- *           doesn't work with a glOrtho projection :)
- *         - solved several problems with homogeneous coordinate and texture mapping
- *         - fixed a bug in all line functions
- *         - fixed a clear framebuffer bug
- *         - solved a display list/teximg problem (but use
- *           glBindTexture: it is several times faster)
- *
- * V0.11 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - introduced texture mapping support (not yet finished !)
- *         - tested with Mesa2.2b6
- *         - the driver is faster 
- *         - written glFlush/glFinish
- *         - the driver print a lot of info about the Glide lib
- *
- * v0.1  - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
- *         - Initial revision
- *
- */
+/* fxapi.c - public interface to FX/Mesa functions (fxmesa.h) */
 
 
 #ifdef HAVE_CONFIG_H
 #if defined(FX)
 #include "fxdrv.h"
 
-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
 
 
 /*
- * Select the Voodoo board to use when creating
- * a new context.
+ * Query 3Dfx hardware presence/kind
  */
-GLboolean GLAPIENTRY fxMesaSelectCurrentBoard(int n)
+static GLboolean GLAPIENTRY fxQueryHardware (void)
 {
-  fxQueryHardware();
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+    fprintf(stderr, "fxQueryHardware()\n");
+ }
 
-  if((n<0) || (n>=glbHWConfig.num_sst))
-    return GL_FALSE;
+ if (!glbGlideInitialized) {
+    grGlideInit();
+    glb3DfxPresent = FX_grSstQueryHardware(&glbHWConfig);
 
-  glbCurrentBoard=n;
+    glbGlideInitialized = 1;
 
-  return GL_TRUE;
+#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;
 }
 
 
-fxMesaContext GLAPIENTRY fxMesaGetCurrentContext(void)
+/*
+ * Select the Voodoo board to use when creating
+ * a new context.
+ */
+GLint GLAPIENTRY fxMesaSelectCurrentBoard (int n)
 {
-  return fxMesaCurrentCtx;
+   fxQueryHardware();
+
+   if ((n < 0) || (n >= glbHWConfig.num_sst))
+      return -1;
+
+   return glbHWConfig.SSTs[glbCurrentBoard = n].type;
 }
 
 
-void GLAPIENTRY fxMesaSetNearFar(GLfloat n, GLfloat f)
+fxMesaContext GLAPIENTRY fxMesaGetCurrentContext (void)
 {
-  if(fxMesaCurrentCtx)
-    fxDDSetNearFar(fxMesaCurrentCtx->glCtx,n,f);
+ return fxMesaCurrentCtx;
 }
 
 
-/*
- * The extension GL_FXMESA_global_texture_lod_bias
- */
-void GLAPIENTRY glGlobalTextureLODBiasFXMESA(GLfloat biasVal)
+void GLAPIENTRY fxGetScreenGeometry (GLint *w, GLint *h)
 {
-  grTexLodBiasValue(GR_TMU0,biasVal);
-
-  if(fxMesaCurrentCtx->haveTwoTMUs)
-    grTexLodBiasValue(GR_TMU1,biasVal);
+ 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;
+ }
 }
 
 
@@ -710,618 +177,768 @@ void GLAPIENTRY glGlobalTextureLODBiasFXMESA(GLfloat biasVal)
  * More a trick than a real extesion, use the shared global
  * palette extension. 
  */
-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]={ 
-    { 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
-    ,{ 1024, 768, GR_RESOLUTION_1280x1024, 8, 8 }
-#endif
-#ifdef GR_RESOLUTION_1600x1200
-    ,{ 1024, 768, GR_RESOLUTION_1600x1200, 16, 8 }
-#endif
-  };
-  int NUM_RESOLUTIONS = sizeof(resolutions) / (sizeof(int)*5);
-  int i,fbmem;
-  GrScreenResolution_t lastvalidres=resolutions[1][2];
+      fprintf(stderr, "gl3DfxSetPaletteEXT(...)\n");
 
-  fxQueryHardware();
-
-  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;
-
-   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;
-        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(verbose)
-      fprintf(stderr,"Mesa fx Voodoo Device Driver v0.30\nWritten by David Bucciarelli (davibu@tin.it.it)\n");
-
-   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;
-   }
-
-   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;
+ 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;
    }
-
-   /* Pixel tables are use during pixel read-back */
-   if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) {
-      fxInitPixelTables(GL_TRUE); /* use BGR pixel order on Voodoo1/2 */
+   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;
    }
-   else {
-      fxInitPixelTables(GL_FALSE); /* use RGB pixel order otherwise */
+   break;
+ default: /* 1 chip */
+   switch(sliaa) {
+   case 1: /* 2 Sample AA */
+     numSLI         = 1;
+     samplesPerChip = 2;
+     break;
+   default:
+     numSLI         = 1;
+     samplesPerChip = 1;
    }
-
-   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->x_offset = 0;
-   fxMesa->y_offset = 0;
-   fxMesa->y_delta = 0;
-   
-   fxMesa->needClip = 0;
-
-   if(verbose)
-      fprintf(stderr,"Glide screen size: %dx%d\n",
-              (int)FX_grSstScreenWidth(),(int)FX_grSstScreenHeight());
-
-   fxMesa->glVis=gl_create_visual(GL_TRUE,     /* RGB mode */
-                                 alphaBuffer,
-                                 doubleBuffer,
-                                 GL_FALSE,    /* stereo */
-                                 depthSize,   /* depth_size */
-                                 stencilSize, /* stencil_size */
-                                 accumSize,   /* accum_size */
-                                 0,           /* index bits */
-                                 5,6,5,0);    /* RGBA bits */
+   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 = "gl_create_visual";
+      str = "_mesa_create_visual";
       goto errorhandler;
    }
 
-   ctx = fxMesa->glCtx=gl_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 = "gl_create_context";
+      str = "_mesa_create_context";
       goto errorhandler;
    }
 
 
-   if (!fxDDInitFxMesaContext( fxMesa )) {
-      errorstr = "fxDDInitFxMesaContext failed"; 
+   if (!fxDDInitFxMesaContext(fxMesa)) {
+      str = "fxDDInitFxMesaContext";
       goto errorhandler;
    }
 
 
-   fxMesa->glBuffer=gl_create_framebuffer(fxMesa->glVis);
+   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 = "gl_create_framebuffer";
+      str = "_mesa_create_framebuffer";
       goto errorhandler;
    }
-  
+
    glbTotNumCtx++;
 
    /* install signal handlers */
 #if defined(__linux__)
-   if (fxMesa->glCtx->CatchSignals) {
-      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);
+   /* Only install if environment var. is not set. */
+   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)
-        gl_destroy_framebuffer(fxMesa->glBuffer);
-      if (fxMesa->glVis)
-        gl_destroy_visual(fxMesa->glVis);
-      if (fxMesa->glCtx)
-        gl_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);
+ }
 
-/*
- * Function to set the new window size in the context (mainly for the Voodoo Rush)
- */
-void GLAPIENTRY fxMesaUpdateScreenSize(fxMesaContext fxMesa)
-{
-  fxMesa->width=FX_grSstScreenWidth();
-  fxMesa->height=FX_grSstScreenHeight();
+ fprintf(stderr, "fxMesaCreateContext: ERROR: %s\n", str);
+ return NULL;
 }
 
 
 /*
- * Destroy the given FX/Mesa context.
+ * Function to set the new window size in the context (mainly for the Voodoo Rush)
  */
-void GLAPIENTRY fxMesaDestroyContext(fxMesaContext fxMesa)
+void GLAPIENTRY
+fxMesaUpdateScreenSize(fxMesaContext fxMesa)
 {
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxMesaDestroyContext()\n");
-  }
-
-  if(fxMesa) {
-    gl_destroy_visual(fxMesa->glVis);
-    gl_destroy_context(fxMesa->glCtx);
-    gl_destroy_framebuffer(fxMesa->glBuffer);
-
-    glbTotNumCtx--;
-
-    fxCloseHardware();
-    FX_grSstWinClose(fxMesa->glideContext);
-
-    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;
-
-      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",
-              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));
-    }
-    if (fxMesa->state)  
-       free(fxMesa->state);
-    if (fxMesa->fogTable)
-       free(fxMesa->fogTable);
-    fxTMClose(fxMesa);
-    
-    free(fxMesa);
-  }
-
-  if(fxMesa==fxMesaCurrentCtx)
-    fxMesaCurrentCtx=NULL;
+   fxMesa->width = FX_grSstScreenWidth();
+   fxMesa->height = FX_grSstScreenHeight();
 }
 
 
 /*
- * Make the specified FX/Mesa context the current one.
+ * Destroy the given FX/Mesa context.
  */
-void GLAPIENTRY fxMesaMakeCurrent(fxMesaContext fxMesa)
+void GLAPIENTRY
+fxMesaDestroyContext(fxMesaContext fxMesa)
 {
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) Start\n");
-  }
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxMesaDestroyContext(...)\n");
+   }
 
-  if(!fxMesa) {
-    gl_make_current(NULL,NULL);
-    fxMesaCurrentCtx=NULL;
+   if (!fxMesa)
+      return;
+
+   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;
+
+      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",
+             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));
+   }
 
-    if (MESA_VERBOSE&VERBOSE_DRIVER) {
-      fprintf(stderr,"fxmesa: fxMesaMakeCurrent(NULL) End\n");
-    }
+   glbTotNumCtx--;
 
-    return;
-  }
+   if (!glbTotNumCtx && getenv("MESA_FX_INFO")) {
+      GrSstPerfStats_t st;
 
-  /* if this context is already the current one, we can return early */
-  if (fxMesaCurrentCtx == fxMesa
-      && fxMesaCurrentCtx->glCtx == gl_get_current_context()) {
-     if (MESA_VERBOSE&VERBOSE_DRIVER) {
-        fprintf(stderr,"fxmesa: fxMesaMakeCurrent(fxMesaCurrentCtx==fxMesa) End\n");
-    }
+      FX_grSstPerfStats(&st);
 
-    return;
-  }
+      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(fxMesaCurrentCtx)
-    grGlideGetState((GrState*)fxMesaCurrentCtx->state);
+   /* [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);
+
+   FREE(fxMesa);
+
+   if (fxMesa == fxMesaCurrentCtx)
+      fxMesaCurrentCtx = NULL;
+}
 
-  fxMesaCurrentCtx=fxMesa;
 
-  grSstSelect(fxMesa->board);
-  grGlideSetState((GrState*)fxMesa->state);
+/*
+ * Make the specified FX/Mesa context the current one.
+ */
+void GLAPIENTRY
+fxMesaMakeCurrent(fxMesaContext fxMesa)
+{
+   if (!fxMesa) {
+      _mesa_make_current(NULL, NULL);
+      fxMesaCurrentCtx = NULL;
 
-  gl_make_current(fxMesa->glCtx,fxMesa->glBuffer);
+      if (TDFX_DEBUG & VERBOSE_DRIVER) {
+        fprintf(stderr, "fxMesaMakeCurrent(NULL)\n");
+      }
 
-  fxSetupDDPointers(fxMesa->glCtx);
+      return;
+   }
 
-  /* 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);
+   /* 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");
+      }
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) End\n");
-  }
-}
+      return;
+   }
 
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxMesaMakeCurrent(...)\n");
+   }
 
-/*
- * Swap front/back buffers for current context if double buffered.
- */
-void GLAPIENTRY fxMesaSwapBuffers(void)
-{
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: ------------------------------- fxMesaSwapBuffers() -------------------------------\n");
-  }
+   if (fxMesaCurrentCtx)
+      grGlideGetState((GrState *) fxMesaCurrentCtx->state);
 
-  if(fxMesaCurrentCtx) {
-   FLUSH_VB( fxMesaCurrentCtx->glCtx, "swap buffers" );
+   fxMesaCurrentCtx = fxMesa;
 
-    if(fxMesaCurrentCtx->haveDoubleBuffer) {
+   grSstSelect(fxMesa->board);
+   grGlideSetState((GrState *) fxMesa->state);
 
-      grBufferSwap(fxMesaCurrentCtx->swapInterval);
+   _mesa_make_current(fxMesa->glCtx, fxMesa->glBuffer);
 
-      /*
-       * 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); */
-        ;
+   fxSetupDDPointers(fxMesa->glCtx);
 
-      fxMesaCurrentCtx->stats.swapBuffer++;
-    }
-  }
+   /* 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);
 }
 
 
 /*
- * Query 3Dfx hardware presence/kind
+ * Swap front/back buffers for current context if double buffered.
  */
-int GLAPIENTRY fxQueryHardware(void)
+void GLAPIENTRY
+fxMesaSwapBuffers(void)
 {
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-    fprintf(stderr,"fxmesa: fxQueryHardware() Start\n");
-  }
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxMesaSwapBuffers()\n");
+   }
 
-  if(!glbGlideInitialized) {
-    grGlideInit();
-    if(FX_grSstQueryHardware(&glbHWConfig)) {
-      grSstSelect(glbCurrentBoard);
-      glb3DfxPresent=1;
-
-      if(getenv("MESA_FX_INFO")) {
-        char buf[80];
-                        
-        FX_grGlideGetVersion(buf);
-        fprintf(stderr,"Using Glide V%s\n","");
-        fprintf(stderr,"Number of boards: %d\n",glbHWConfig.num_sst);
-
-        if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
-          fprintf(stderr,"Framebuffer RAM: %d\n",
-                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ?
-                  (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam*2) :
-                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam);
-          fprintf(stderr,"Number of TMUs: %d\n",
-                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx);
-          fprintf(stderr,"SLI detected: %d\n",
-                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect);
-        } else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) {
-          fprintf(stderr,"Framebuffer RAM: %d\n",
-                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam);
-          fprintf(stderr,"Number of TMUs: %d\n",
-                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx);
-        }
+   if (fxMesaCurrentCtx) {
+      _mesa_notifySwapBuffers(fxMesaCurrentCtx->glCtx);
 
-      }
-    } else
-      glb3DfxPresent=0;
+      if (fxMesaCurrentCtx->haveDoubleBuffer) {
 
-    glbGlideInitialized=1;
+        grBufferSwap(fxMesaCurrentCtx->swapInterval);
 
-#if defined(__WIN32__)
-    onexit((_onexit_t)cleangraphics);
-#elif defined(__linux__)
-    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(!glb3DfxPresent) {
-    if (MESA_VERBOSE&VERBOSE_DRIVER) {
-      fprintf(stderr,"fxmesa: fxQueryHardware() End (-1)\n");
-    }
-    return(-1);
-  }
-
-  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;
+      }
+   }
 }
 
 
@@ -1331,10 +948,11 @@ void GLAPIENTRY fxCloseHardware(void)
 /*
  * Need this to provide at least one external definition.
  */
-
-int gl_fx_dummy_function_api(void)
+extern int gl_fx_dummy_function_api(void);
+int
+gl_fx_dummy_function_api(void)
 {
-  return 0;
+   return 0;
 }
 
-#endif  /* FX */
+#endif /* FX */