summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/glide
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/glide')
-rw-r--r--src/mesa/drivers/glide/fxapi.c1411
-rw-r--r--src/mesa/drivers/glide/fxdd.c632
-rw-r--r--src/mesa/drivers/glide/fxddspan.c817
-rw-r--r--src/mesa/drivers/glide/fxddtex.c1299
-rw-r--r--src/mesa/drivers/glide/fxdrv.h576
-rw-r--r--src/mesa/drivers/glide/fxglidew.c247
-rw-r--r--src/mesa/drivers/glide/fxglidew.h358
-rw-r--r--src/mesa/drivers/glide/fxopengl.def467
-rw-r--r--src/mesa/drivers/glide/fxsetup.c1552
-rw-r--r--src/mesa/drivers/glide/fxtexman.c579
-rw-r--r--src/mesa/drivers/glide/fxwgl.c806
11 files changed, 8744 insertions, 0 deletions
diff --git a/src/mesa/drivers/glide/fxapi.c b/src/mesa/drivers/glide/fxapi.c
new file mode 100644
index 0000000000..fbc586e757
--- /dev/null
+++ b/src/mesa/drivers/glide/fxapi.c
@@ -0,0 +1,1411 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxapi.c - 3Dfx VooDoo/Mesa interface
+*/
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+ *
+ * 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
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+#include "fxdrv.h"
+
+fxMesaContext fxMesaCurrentCtx=NULL;
+
+/*
+ * Status of 3Dfx hardware initialization
+ */
+
+static int glbGlideInitialized=0;
+static int glb3DfxPresent=0;
+static int glbTotNumCtx=0;
+
+GrHwConfiguration glbHWConfig;
+int glbCurrentBoard=0;
+
+
+#if defined(__WIN32__)
+static int cleangraphics(void)
+{
+ glbTotNumCtx=1;
+ fxMesaDestroyContext(fxMesaCurrentCtx);
+
+ return 0;
+}
+#elif defined(__linux__)
+static void cleangraphics(void)
+{
+ glbTotNumCtx=1;
+ fxMesaDestroyContext(fxMesaCurrentCtx);
+}
+
+static void cleangraphics_handler(int s)
+{
+ fprintf(stderr,"fxmesa: Received a not handled signal %d\n",s);
+
+ cleangraphics();
+/* abort(); */
+ exit(1);
+}
+#endif
+
+
+/*
+ * Select the Voodoo board to use when creating
+ * a new context.
+ */
+GLboolean GLAPIENTRY fxMesaSelectCurrentBoard(int n)
+{
+ fxQueryHardware();
+
+ if((n<0) || (n>=glbHWConfig.num_sst))
+ return GL_FALSE;
+
+ glbCurrentBoard=n;
+
+ return GL_TRUE;
+}
+
+
+fxMesaContext GLAPIENTRY fxMesaGetCurrentContext(void)
+{
+ return fxMesaCurrentCtx;
+}
+
+
+void GLAPIENTRY fxMesaSetNearFar(GLfloat n, GLfloat f)
+{
+ if(fxMesaCurrentCtx)
+ fxDDSetNearFar(fxMesaCurrentCtx->glCtx,n,f);
+}
+
+
+/*
+ * The extension GL_FXMESA_global_texture_lod_bias
+ */
+void GLAPIENTRY glGlobalTextureLODBiasFXMESA(GLfloat biasVal)
+{
+ grTexLodBiasValue(GR_TMU0,biasVal);
+
+ if(fxMesaCurrentCtx->haveTwoTMUs)
+ grTexLodBiasValue(GR_TMU1,biasVal);
+}
+
+
+/*
+ * The 3Dfx Global Palette extension for GLQuake.
+ * More a trick than a real extesion, use the shared global
+ * palette extension.
+ */
+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);
+ }
+}
+
+
+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];
+
+ fxQueryHardware();
+
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
+ fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam;
+
+ 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;
+
+ /* A work around for BZFlag */
+
+ 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];
+
+ lastvalidres=resolutions[i][2];
+ }
+
+ return lastvalidres;
+}
+
+
+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;
+ }
+ }
+
+ res=fxBestResolution(width,height,aux);
+
+ return fxMesaCreateContext(win,res,refresh,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 fxMesa;
+ 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) {
+ if(type==GR_SSTTYPE_VOODOO)
+ win=0;
+
+ grSstSelect(glbCurrentBoard);
+
+#if FXMESA_USE_ARGB
+ glideContext = FX_grSstWinOpen((FxU32)win,res,ref,
+ GR_COLORFORMAT_ARGB,GR_ORIGIN_LOWER_LEFT,2,aux);
+
+#else
+ glideContext = FX_grSstWinOpen((FxU32)win,res,ref,
+ GR_COLORFORMAT_ABGR,GR_ORIGIN_LOWER_LEFT,2,aux);
+#endif
+ if (!glideContext){
+ errorstr = "grSstWinOpen";
+ goto errorhandler;
+ }
+
+ if(verbose)
+ fprintf(stderr,"Glide screen size: %dx%d\n",
+ (int)FX_grSstScreenWidth(),(int)FX_grSstScreenHeight());
+ } else {
+ fprintf(stderr,"fx Driver: ERROR no Voodoo1/2 Graphics or Voodoo Rush !\n");
+ return NULL;
+ }
+
+ fxMesa=(fxMesaContext)calloc(1,sizeof(struct tfxMesaContext));
+ if(!fxMesa) {
+ errorstr = "malloc";
+ goto errorhandler;
+ }
+
+ FX_setupGrVertexLayout();
+
+ fxMesa->glideContext = glideContext;
+ fxMesa->board=glbCurrentBoard;
+ fxMesa->width=FX_grSstScreenWidth();
+ fxMesa->height=FX_grSstScreenHeight();
+
+ fxMesa->verbose=verbose;
+
+ 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;
+
+ if (getenv("FX_EMULATE_SINGLE_TMU")) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ fprintf(stderr, "\n\nEmulating single tmu\n\n");
+ fxMesa->haveTwoTMUs = GL_FALSE;
+ }
+
+ fxMesa->emulateTwoTMUs = fxMesa->haveTwoTMUs;
+
+ if (!getenv("FX_DONT_FAKE_MULTITEX")) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ if (!fxMesa->haveTwoTMUs)
+ fprintf(stderr, "\n\nEmulating multitexture\n\n");
+ }
+ fxMesa->emulateTwoTMUs = GL_TRUE;
+ }
+
+
+ fxMesa->haveDoubleBuffer=doubleBuffer;
+ fxMesa->haveAlphaBuffer=alphaBuffer;
+ fxMesa->haveGlobalPaletteTexture=GL_FALSE;
+
+ if(getenv("FX_GLIDE_SWAPINTERVAL"))
+ fxMesa->swapInterval=atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
+ else
+ fxMesa->swapInterval=1;
+
+ if(getenv("MESA_FX_SWAP_PENDING"))
+ fxMesa->maxPendingSwapBuffers=atoi(getenv("MESA_FX_SWAP_PENDING"));
+ else
+ fxMesa->maxPendingSwapBuffers=2;
+
+ fxMesa->color=0xffffffff;
+ fxMesa->clearC=0;
+ fxMesa->clearA=0;
+
+ fxMesa->stats.swapBuffer=0;
+ fxMesa->stats.reqTexUpload=0;
+ fxMesa->stats.texUpload=0;
+ fxMesa->stats.memTexUpload=0;
+
+ fxMesa->tmuSrc=FX_TMU_NONE;
+ fxMesa->lastUnitsMode=FX_UM_NONE;
+ fxTMInit(fxMesa);
+
+ /* FX units setup */
+
+ fxMesa->unitsState.alphaTestEnabled=GL_FALSE;
+ fxMesa->unitsState.alphaTestFunc=GR_CMP_ALWAYS;
+ fxMesa->unitsState.alphaTestRefValue=0;
+
+ fxMesa->unitsState.blendEnabled=GL_FALSE;
+ fxMesa->unitsState.blendSrcFuncRGB=GR_BLEND_ONE;
+ fxMesa->unitsState.blendDstFuncRGB=GR_BLEND_ZERO;
+ fxMesa->unitsState.blendSrcFuncAlpha=GR_BLEND_ONE;
+ fxMesa->unitsState.blendDstFuncAlpha=GR_BLEND_ZERO;
+
+ fxMesa->unitsState.depthTestEnabled =GL_FALSE;
+ fxMesa->unitsState.depthMask =GL_TRUE;
+ fxMesa->unitsState.depthTestFunc =GR_CMP_LESS;
+
+ grColorMask(FXTRUE,alphaBuffer ? FXTRUE : FXFALSE);
+ if(doubleBuffer) {
+ fxMesa->currentFB=GR_BUFFER_BACKBUFFER;
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ } else {
+ fxMesa->currentFB=GR_BUFFER_FRONTBUFFER;
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ }
+
+ fxMesa->state = NULL;
+ fxMesa->fogTable = NULL;
+
+ fxMesa->state = malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE));
+ fxMesa->fogTable = malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES)*sizeof(GrFog_t));
+
+ if (!fxMesa->state || !fxMesa->fogTable) {
+ errorstr = "malloc";
+ goto errorhandler;
+ }
+
+ if(depthSize)
+ grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
+
+#if (!FXMESA_USE_ARGB)
+ grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); /* Not every Glide supports this */
+#endif
+
+ 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->glVis) {
+ errorstr = "gl_create_visual";
+ goto errorhandler;
+ }
+
+ ctx = fxMesa->glCtx=gl_create_context(fxMesa->glVis,
+ shareCtx, /* share list context */
+ (void *) fxMesa, GL_TRUE);
+ if (!ctx) {
+ errorstr = "gl_create_context";
+ goto errorhandler;
+ }
+
+ fxMesa->glBuffer=gl_create_framebuffer(fxMesa->glVis);
+ if (!fxMesa->glBuffer) {
+ errorstr = "gl_create_framebuffer";
+ goto errorhandler;
+ }
+
+ fxMesa->glCtx->Const.MaxTextureLevels=9;
+ fxMesa->glCtx->Const.MaxTextureSize=256;
+ fxMesa->glCtx->Const.MaxTextureUnits=fxMesa->emulateTwoTMUs ? 2 : 1;
+
+ fxMesa->glCtx->NewState|=NEW_DRVSTATE1;
+ fxMesa->new_state = NEW_ALL;
+
+ fxDDSetupInit();
+ fxDDCvaInit();
+ fxDDClipInit();
+ fxDDTrifuncInit();
+ fxDDFastPathInit();
+
+ fxSetupDDPointers(fxMesa->glCtx);
+ fxDDRenderInit(fxMesa->glCtx);
+ fxDDInitExtensions(fxMesa->glCtx);
+
+ fxDDSetNearFar(fxMesa->glCtx,1.0,100.0);
+
+ grGlideGetState((GrState*)fxMesa->state);
+
+ /* XXX Fix me: callback not registered when main VB is created.
+ */
+ if (fxMesa->glCtx->VB)
+ fxDDRegisterVB( fxMesa->glCtx->VB );
+
+ /* XXX Fix me too: need to have the 'struct dd' prepared prior to
+ * creating the context... The below is broken if you try to insert
+ * new stages.
+ */
+ if (ctx->NrPipelineStages)
+ ctx->NrPipelineStages = fxDDRegisterPipelineStages( ctx->PipelineStage,
+ ctx->PipelineStage,
+ ctx->NrPipelineStages);
+
+
+ glbTotNumCtx++;
+
+ /* Run the config file */
+ gl_context_initialize( fxMesa->glCtx );
+
+ /* 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);
+ }
+#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 && 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;
+}
+
+
+/*
+ * 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();
+}
+
+
+/*
+ * Destroy the given FX/Mesa context.
+ */
+void GLAPIENTRY fxMesaDestroyContext(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;
+}
+
+
+/*
+ * Make the specified FX/Mesa context the current one.
+ */
+void GLAPIENTRY fxMesaMakeCurrent(fxMesaContext fxMesa)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) Start\n");
+ }
+
+ if(!fxMesa) {
+ gl_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 == gl_get_current_context()) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaMakeCurrent(fxMesaCurrentCtx==fxMesa) End\n");
+ }
+
+ return;
+ }
+
+ if(fxMesaCurrentCtx)
+ grGlideGetState((GrState*)fxMesaCurrentCtx->state);
+
+ fxMesaCurrentCtx=fxMesa;
+
+ grSstSelect(fxMesa->board);
+ grGlideSetState((GrState*)fxMesa->state);
+
+ gl_make_current(fxMesa->glCtx,fxMesa->glBuffer);
+
+ fxSetupDDPointers(fxMesa->glCtx);
+
+ /* 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 (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) End\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) {
+ FLUSH_VB( fxMesaCurrentCtx->glCtx, "swap buffers" );
+
+ 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++;
+ }
+ }
+}
+
+
+/*
+ * Query 3Dfx hardware presence/kind
+ */
+int GLAPIENTRY fxQueryHardware(void)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxQueryHardware() Start\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",0);
+ 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);
+ }
+
+ }
+ } else
+ glb3DfxPresent=0;
+
+ glbGlideInitialized=1;
+
+#if defined(__WIN32__)
+ onexit((_onexit_t)cleangraphics);
+#elif defined(__linux__)
+ atexit(cleangraphics);
+#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);
+}
+
+
+/*
+ * Shutdown Glide library
+ */
+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;
+ }
+ }
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_api(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxdd.c b/src/mesa/drivers/glide/fxdd.c
new file mode 100644
index 0000000000..b2f3a7a43c
--- /dev/null
+++ b/src/mesa/drivers/glide/fxdd.c
@@ -0,0 +1,632 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxdd.c - 3Dfx VooDoo Mesa device driver functions
+*/
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "enums.h"
+
+/**********************************************************************/
+/***** Miscellaneous functions *****/
+/**********************************************************************/
+
+/* Enalbe/Disable dithering */
+void fxDDDither(GLcontext *ctx, GLboolean enable)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDDither()\n");
+ }
+
+ if(enable)
+ grDitherMode(GR_DITHER_4x4);
+ else
+ grDitherMode(GR_DITHER_DISABLE);
+}
+
+
+/* Return buffer size information */
+void fxDDBufferSize(GLcontext *ctx, GLuint *width, GLuint *height)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDBufferSize(...) Start\n");
+ }
+
+ *width=fxMesa->width;
+ *height=fxMesa->height;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDBufferSize(...) End\n");
+ }
+}
+
+
+/* Set current drawing color */
+static void fxDDSetColor(GLcontext *ctx, GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLubyte col[4];
+ ASSIGN_4V( col, red, green, blue, alpha );
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
+ }
+
+ fxMesa->color=FXCOLOR4(col);
+}
+
+
+/* Implements glClearColor() */
+static void fxDDClearColor(GLcontext *ctx, GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLubyte col[4];
+
+
+
+ ASSIGN_4V( col, red, green, blue, 255 );
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
+ }
+
+ fxMesa->clearC=FXCOLOR4( col );
+ fxMesa->clearA=alpha;
+}
+
+/* Clear the color and/or depth buffers */
+static GLbitfield fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLbitfield newmask;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDClear(%d,%d,%d,%d)\n",x,y,width,height);
+ }
+
+ switch(mask & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) {
+ case (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT):
+ /* clear color and depth buffer */
+
+ if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA,
+ (FxU16)(ctx->Depth.Clear*0xffff));
+ }
+ if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA,
+ (FxU16)(ctx->Depth.Clear*0xffff));
+ }
+
+ newmask=mask & (~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT));
+ break;
+ case (GL_COLOR_BUFFER_BIT):
+ /* clear color buffer */
+
+ if(ctx->Color.ColorMask) {
+ grDepthMask(FXFALSE);
+
+ if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA, 0);
+ }
+ if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA, 0);
+ }
+
+ if(ctx->Depth.Mask)
+ grDepthMask(FXTRUE);
+ }
+
+ newmask=mask & (~(GL_COLOR_BUFFER_BIT));
+ break;
+ case (GL_DEPTH_BUFFER_BIT):
+ /* clear depth buffer */
+
+ if(ctx->Depth.Mask) {
+ grColorMask(FXFALSE,FXFALSE);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA,
+ (FxU16)(ctx->Depth.Clear*0xffff));
+
+ grColorMask(ctx->Color.ColorMask[RCOMP] ||
+ ctx->Color.ColorMask[GCOMP] ||
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer);
+ }
+
+ newmask=mask & (~(GL_DEPTH_BUFFER_BIT));
+ break;
+ default:
+ newmask=mask;
+ break;
+ }
+
+ return newmask;
+}
+
+
+/* Set the buffer used in double buffering */
+static GLboolean fxDDSetBuffer(GLcontext *ctx, GLenum mode )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDSetBuffer(%x)\n",mode);
+ }
+
+ if (mode == GL_FRONT_LEFT) {
+ fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ return GL_TRUE;
+ }
+ else if (mode == GL_BACK_LEFT) {
+ fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean fxDDDrawBitMap(GLcontext *ctx, GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ FxU16 *p;
+ GrLfbInfo_t info;
+ const GLubyte *pb;
+ int x,y;
+ GLint r,g,b,a,scrwidth,scrheight,stride;
+ FxU16 color;
+
+ /* TODO: with a little work, these bitmap unpacking parameter restrictions
+ * could be removed.
+ */
+ if((unpack->Alignment!=1) ||
+ (unpack->RowLength!=0) ||
+ (unpack->SkipPixels!=0) ||
+ (unpack->SkipRows!=0) ||
+ (unpack->SwapBytes) ||
+ (unpack->LsbFirst))
+ return GL_FALSE;
+
+#define ISCLIPPED(rx) ( ((rx)<0) || ((rx)>=scrwidth) )
+#define DRAWBIT(i) { \
+ if(!ISCLIPPED(x+px)) \
+ if( (*pb) & (1<<(i)) ) \
+ (*p)=color; \
+ p++; \
+ x++; \
+ if(x>=width) { \
+ pb++; \
+ break; \
+ } \
+}
+
+ scrwidth=fxMesa->width;
+ scrheight=fxMesa->height;
+
+ if((px>=scrwidth) || (px+width<=0) || (py>=scrheight) || (py+height<=0))
+ return GL_TRUE;
+
+ pb=bitmap;
+
+ if(py<0) {
+ pb+=(height*(-py)) >> (3+1);
+ height+=py;
+ py=0;
+ }
+
+ if(py+height>=scrheight)
+ height-=(py+height)-scrheight;
+
+ info.size=sizeof(info);
+ if(!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_565,
+ GR_ORIGIN_UPPER_LEFT,
+ FXFALSE,
+ &info)) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: error locking the linear frame buffer\n");
+#endif
+ return GL_TRUE;
+ }
+
+ r=(GLint)(ctx->Current.RasterColor[0]*255.0f);
+ g=(GLint)(ctx->Current.RasterColor[1]*255.0f);
+ b=(GLint)(ctx->Current.RasterColor[2]*255.0f);
+ a=(GLint)(ctx->Current.RasterColor[3]*255.0f);
+ color=(FxU16)
+ ( ((FxU16)0xf8 & b) <<(11-3)) |
+ ( ((FxU16)0xfc & g) <<(5-3+1)) |
+ ( ((FxU16)0xf8 & r) >> 3);
+
+ stride=info.strideInBytes>>1;
+
+ /* This code is a bit slow... */
+
+ for(y=0;y<height;y++) {
+ p=((FxU16 *)info.lfbPtr)+px+((scrheight-(y+py))*stride);
+
+ for(x=0;;) {
+ DRAWBIT(7); DRAWBIT(6); DRAWBIT(5); DRAWBIT(4);
+ DRAWBIT(3); DRAWBIT(2); DRAWBIT(1); DRAWBIT(0);
+ pb++;
+ }
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY,fxMesa->currentFB);
+
+#undef ISCLIPPED
+#undef DRAWBIT
+
+ return GL_TRUE;
+}
+
+static void fxDDFinish(GLcontext *ctx)
+{
+ FX_grFlush();
+}
+
+
+static GLint fxDDGetParameteri(const GLcontext *ctx, GLint param)
+{
+ switch(param) {
+ case DD_HAVE_HARDWARE_FOG:
+ return 1;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxDDGetParameteri(): %x\n",param);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+
+void fxDDSetNearFar(GLcontext *ctx, GLfloat n, GLfloat f)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+/* KW: Put the word Mesa in the render string because quakeworld
+ * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
+ * Why?
+ */
+static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name)
+{
+ static char *extensions="GL_EXT_blend_color GL_EXT_blend_minmax GL_EXT_blend_logic_op GL_EXT_blend_subtract GL_EXT_paletted_texture GL_EXT_point_parameters GL_EXT_polygon_offset GL_EXT_vertex_array GL_EXT_texture_object GL_EXT_texture3D GL_MESA_window_pos GL_MESA_resize_buffers GL_EXT_shared_texture_palette GL_EXT_rescale_normal GL_EXT_abgr GL_SGIS_texture_edge_clamp 3DFX_set_global_palette GL_FXMESA_global_texture_lod_bias";
+
+ static char buf[MAX_NUM_SST][64];
+
+ fxQueryHardware();
+
+ switch (name) {
+ case GL_RENDERER:
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
+ sprintf(buf[glbCurrentBoard],"Mesa Glide v0.30 Voodoo_Graphics %d CARD/%d FB/%d TM/%d TMU/%s",
+ glbCurrentBoard,
+
+ (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ?
+ (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam*2) :
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam),
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.tmuConfig[GR_TMU0].tmuRam+
+ ((glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx>1) ?
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.tmuConfig[GR_TMU1].tmuRam :
+ 0),
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx,
+
+ (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ? "SLI" : "NOSLI")
+ );
+ }
+ else {
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96)
+ sprintf(buf[glbCurrentBoard],"Glide v0.30 Voodoo_Rush %d CARD/%d FB/%d TM/%d TMU/NOSLI",
+ glbCurrentBoard,
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam,
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.tmuConfig.tmuRam,
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx
+ );
+ else
+ strcpy(buf[glbCurrentBoard],"Glide v0.30 UNKNOWN");
+ }
+ return (GLubyte *) buf[glbCurrentBoard];
+ case GL_EXTENSIONS:
+ return (GLubyte *) extensions;
+ default:
+ return NULL;
+ }
+}
+
+
+void fxDDInitExtensions( GLcontext *ctx )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ gl_extensions_add( ctx, DEFAULT_ON, "3DFX_set_global_palette", 0 );
+ gl_extensions_add( ctx, DEFAULT_ON, "GL_FXMESA_global_texture_lod_bias", 0);
+
+ if (!fxMesa->emulateTwoTMUs)
+ gl_extensions_disable( ctx, "GL_ARB_multitexture" );
+}
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+/* This is a no-op, since the z-buffer is in hardware */
+static void fxAllocDepthBuffer(GLcontext *ctx)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxAllocDepthBuffer()\n");
+ }
+}
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+/* Check if the hardware supports the current context
+ *
+ * Performs similar work to fxDDChooseRenderState() - should be merged.
+ */
+static GLboolean fxIsInHardware(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (!ctx->Hint.AllowDrawMem)
+ return GL_TRUE; /* you'll take it and like it */
+
+ if((ctx->RasterMask & STENCIL_BIT) ||
+ ((ctx->Color.BlendEnabled) && (ctx->Color.BlendEquation!=GL_FUNC_ADD_EXT)) ||
+ ((ctx->Color.ColorLogicOpEnabled) && (ctx->Color.LogicOp!=GL_COPY)) ||
+ (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) ||
+ (!((ctx->Color.ColorMask[RCOMP]==ctx->Color.ColorMask[GCOMP]) &&
+ (ctx->Color.ColorMask[GCOMP]==ctx->Color.ColorMask[BCOMP]) &&
+ (ctx->Color.ColorMask[ACOMP]==ctx->Color.ColorMask[ACOMP])))
+ )
+ return GL_FALSE;
+
+ /* Unsupported texture/multitexture cases */
+
+ if(fxMesa->emulateTwoTMUs) {
+ if((ctx->Enabled & (TEXTURE0_3D | TEXTURE1_3D)) ||
+ /* Not very well written ... */
+ ((ctx->Enabled & (TEXTURE0_1D | TEXTURE1_1D)) &&
+ ((ctx->Enabled & (TEXTURE0_2D | TEXTURE1_2D))!=(TEXTURE0_2D | TEXTURE1_2D)))
+ )
+ return GL_FALSE;
+
+ if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) &&
+ (ctx->Texture.Unit[0].EnvMode==GL_BLEND))
+ return GL_FALSE;
+
+ if((ctx->Texture.ReallyEnabled & TEXTURE1_2D) &&
+ (ctx->Texture.Unit[1].EnvMode==GL_BLEND))
+ return GL_FALSE;
+
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+ /* KW: This was wrong (I think) and I changed it... which doesn't mean
+ * it is now correct...
+ */
+ if((ctx->Enabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) &&
+ (ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)))
+ {
+ /* Can't use multipass to blend a multitextured triangle - fall
+ * back to software.
+ */
+ if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled)
+ return GL_FALSE;
+
+ if ((ctx->Texture.Unit[0].EnvMode!=ctx->Texture.Unit[1].EnvMode) &&
+ (ctx->Texture.Unit[0].EnvMode!=GL_MODULATE) &&
+ (ctx->Texture.Unit[0].EnvMode!=GL_REPLACE)) /* q2, seems ok... */
+ {
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ fprintf(stderr, "fxMesa: unsupported multitex env mode\n");
+
+ return GL_FALSE;
+ }
+ }
+ } else {
+ if((ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) ||
+ /* Not very well written ... */
+ ((ctx->Enabled & TEXTURE0_1D) &&
+ (!(ctx->Enabled & TEXTURE0_2D)))
+ )
+ return GL_FALSE;
+
+
+ if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) &&
+ (ctx->Texture.Unit[0].EnvMode==GL_BLEND))
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+#define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|NEW_PROJECTION|NEW_TEXTURE_MATRIX|NEW_USER_CLIP|NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE))
+
+static void fxDDUpdateDDPointers(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint new_state = ctx->NewState;
+
+ if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_STATE))
+ fprintf(stderr,"fxmesa: fxDDUpdateDDPointers(...)\n");
+
+ if (new_state & (NEW_RASTER_OPS|NEW_TEXTURING))
+ fxMesa->is_in_hardware = fxIsInHardware(ctx);
+
+ if (fxMesa->is_in_hardware) {
+ if (fxMesa->new_state)
+ fxSetupFXUnits(ctx);
+
+ if(new_state & INTERESTED) {
+ fxDDChooseRenderState( ctx );
+ fxMesa->RenderVBTables=fxDDChooseRenderVBTables(ctx);
+ ctx->Driver.RasterSetup=fxDDChooseSetupFunction(ctx);
+ }
+
+ ctx->Driver.PointsFunc=fxMesa->PointsFunc;
+ ctx->Driver.LineFunc=fxMesa->LineFunc;
+ ctx->Driver.TriangleFunc=fxMesa->TriangleFunc;
+ ctx->Driver.QuadFunc=fxMesa->QuadFunc;
+ ctx->Driver.RenderVBClippedTab=fxMesa->RenderVBTables[0];
+ ctx->Driver.RenderVBCulledTab=fxMesa->RenderVBTables[1];
+ ctx->Driver.RenderVBRawTab=fxMesa->RenderVBTables[2];
+
+ }
+
+ ctx->Driver.AllocDepthBuffer=fxAllocDepthBuffer;
+ ctx->Driver.DepthTestSpan=fxDDDepthTestSpanGeneric;
+ ctx->Driver.DepthTestPixels=fxDDDepthTestPixelsGeneric;
+ ctx->Driver.ReadDepthSpanFloat=fxDDReadDepthSpanFloat;
+ ctx->Driver.ReadDepthSpanInt=fxDDReadDepthSpanInt;
+ ctx->Driver.RenderStart = 0;
+}
+
+
+void fxSetupDDPointers(GLcontext *ctx)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupDDPointers()\n");
+ }
+
+ ctx->Driver.UpdateState=fxDDUpdateDDPointers;
+
+ ctx->Driver.GetString=fxDDGetString;
+
+ ctx->Driver.Dither=fxDDDither;
+
+ ctx->Driver.NearFar=fxDDSetNearFar;
+
+ ctx->Driver.GetParameteri=fxDDGetParameteri;
+
+ ctx->Driver.ClearIndex=NULL;
+ ctx->Driver.ClearColor=fxDDClearColor;
+ ctx->Driver.Clear=fxDDClear;
+
+ ctx->Driver.Index=NULL;
+ ctx->Driver.Color=fxDDSetColor;
+
+ ctx->Driver.SetBuffer=fxDDSetBuffer;
+ ctx->Driver.GetBufferSize=fxDDBufferSize;
+
+ ctx->Driver.Bitmap=fxDDDrawBitMap;
+ ctx->Driver.DrawPixels=NULL;
+
+ ctx->Driver.Finish=fxDDFinish;
+ ctx->Driver.Flush=NULL;
+
+ ctx->Driver.RenderStart=NULL;
+ ctx->Driver.RenderFinish=NULL;
+
+ ctx->Driver.TexEnv=fxDDTexEnv;
+ ctx->Driver.TexImage=fxDDTexImg;
+ ctx->Driver.TexSubImage=fxDDTexSubImg;
+ ctx->Driver.TexParameter=fxDDTexParam;
+ ctx->Driver.BindTexture=fxDDTexBind;
+ ctx->Driver.DeleteTexture=fxDDTexDel;
+ ctx->Driver.UpdateTexturePalette=fxDDTexPalette;
+ ctx->Driver.UseGlobalTexturePalette=fxDDTexUseGlbPalette;
+
+ ctx->Driver.RectFunc=NULL;
+
+ ctx->Driver.AlphaFunc=fxDDAlphaFunc;
+ ctx->Driver.BlendFunc=fxDDBlendFunc;
+ ctx->Driver.DepthFunc=fxDDDepthFunc;
+ ctx->Driver.DepthMask=fxDDDepthMask;
+ ctx->Driver.ColorMask=fxDDColorMask;
+ ctx->Driver.Fogfv=fxDDFogfv;
+ ctx->Driver.Scissor=fxDDScissor;
+ ctx->Driver.FrontFace=fxDDFrontFace;
+ ctx->Driver.CullFace=fxDDCullFace;
+ ctx->Driver.ShadeModel=fxDDShadeModel;
+ ctx->Driver.Enable=fxDDEnable;
+
+
+ ctx->Driver.RegisterVB=fxDDRegisterVB;
+ ctx->Driver.UnregisterVB=fxDDUnregisterVB;
+
+ ctx->Driver.RegisterPipelineStages = fxDDRegisterPipelineStages;
+
+ ctx->Driver.OptimizeImmediatePipeline = 0; /* nothing done yet */
+ ctx->Driver.OptimizePrecalcPipeline = 0;
+
+/* if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */
+/* ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */
+
+ if (!getenv("FX_NO_FAST"))
+ ctx->Driver.BuildPrecalcPipeline = fxDDBuildPrecalcPipeline;
+
+ ctx->Driver.TriangleCaps = DD_TRI_CULL|DD_TRI_OFFSET|DD_TRI_LIGHT_TWOSIDE;
+
+ fxSetupDDSpanPointers(ctx);
+
+ FX_CONTEXT(ctx)->render_index = 1; /* force an update */
+ fxDDUpdateDDPointers(ctx);
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_dd(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxddspan.c b/src/mesa/drivers/glide/fxddspan.c
new file mode 100644
index 0000000000..fc7c38d5c4
--- /dev/null
+++ b/src/mesa/drivers/glide/fxddspan.c
@@ -0,0 +1,817 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxdd.c - 3Dfx VooDoo Mesa span and pixel functions
+*/
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+
+#ifdef _MSC_VER
+#ifdef _WIN32
+#pragma warning( disable : 4090 4022 )
+/* 4101 : "different 'const' qualifier"
+ * 4022 : "pointer mistmatch for actual parameter 'n'
+ */
+#endif
+#endif
+
+
+#if !defined(FXMESA_USE_ARGB)
+
+ #define LFB_WRITE_SPAN_MESA(dst_buffer,dst_x,dst_y,src_width,src_stride,src_data) \
+ grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_width,1,GR_LFB_SRC_FMT_8888,src_stride,src_data)
+#else /* defined(FXMESA_USE_RGBA) */
+
+ #define MESACOLOR_TO_ARGB(c) ( \
+ ( ((unsigned int)(c[ACOMP]))<<24 ) | \
+ ( ((unsigned int)(c[RCOMP]))<<16 ) | \
+ ( ((unsigned int)(c[GCOMP]))<<8 ) | \
+ ( (unsigned int)(c[BCOMP])) )
+
+ /* inline */ void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
+ FxU32 dst_x, FxU32 dst_y,
+ /* GrLfbSrcFmt_t src_format, format is GR_LFB_SRC_FMT_8888 */
+ FxU32 src_width,/* FxU32 src_height, height is 1 */
+ FxI32 src_stride, void *src_data )
+ {
+ /* Covert to ARGB */
+ GLubyte (*rgba)[4] = src_data;
+ GLuint argb[MAX_WIDTH];
+ int i;
+
+ for (i = 0; i < src_width; i++)
+ {
+ argb[i] = MESACOLOR_TO_ARGB(rgba[i]);
+ }
+ FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,GR_LFB_SRC_FMT_8888,src_width,1,src_stride,(void*)argb);
+ }
+#endif
+
+/************************************************************************/
+/***** Span functions *****/
+/************************************************************************/
+
+static void fxDDWriteRGBASpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteRGBASpan(...)\n");
+ }
+
+ if (mask) {
+ int span=0;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ++span;
+ } else {
+ if (span > 0) {
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y,
+ /* GR_LFB_SRC_FMT_8888,*/ span, /*1,*/ 0, (void *) rgba[i-span] );
+ span = 0;
+ }
+ }
+ }
+
+ if (span > 0)
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y,
+ /* GR_LFB_SRC_FMT_8888, */ span, /*1,*/ 0, (void *) rgba[n-span] );
+ } else
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/
+ n,/* 1,*/ 0, (void *) rgba );
+}
+
+
+static void fxDDWriteRGBSpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLubyte rgba[MAX_WIDTH][4];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteRGBSpan()\n");
+ }
+
+ if (mask) {
+ int span=0;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[span][RCOMP] = rgb[i][0];
+ rgba[span][GCOMP] = rgb[i][1];
+ rgba[span][BCOMP] = rgb[i][2];
+ rgba[span][ACOMP] = 255;
+ ++span;
+ } else {
+ if (span > 0) {
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y,
+ /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba );
+ span = 0;
+ }
+ }
+ }
+
+ if (span > 0)
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y,
+ /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba );
+ } else {
+ for (i=0;i<n;i++) {
+ rgba[i][RCOMP]=rgb[i][0];
+ rgba[i][GCOMP]=rgb[i][1];
+ rgba[i][BCOMP]=rgb[i][2];
+ rgba[i][ACOMP]=255;
+ }
+
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/
+ n,/* 1,*/ 0, (void *) rgba );
+ }
+}
+
+
+static void fxDDWriteMonoRGBASpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLuint data[MAX_WIDTH];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteMonoRGBASpan(...)\n");
+ }
+
+ if (mask) {
+ int span=0;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ data[span] = (GLuint) fxMesa->color;
+ ++span;
+ } else {
+ if (span > 0) {
+ FX_grLfbWriteRegion( fxMesa->currentFB, x+i-span, bottom-y,
+ GR_LFB_SRC_FMT_8888, span, 1, 0,
+ (void *) data );
+ span = 0;
+ }
+ }
+ }
+
+ if (span > 0)
+ FX_grLfbWriteRegion( fxMesa->currentFB, x+n-span, bottom-y,
+ GR_LFB_SRC_FMT_8888, span, 1, 0,
+ (void *) data );
+ } else {
+ for (i=0;i<n;i++) {
+ data[i]=(GLuint) fxMesa->color;
+ }
+
+ FX_grLfbWriteRegion( fxMesa->currentFB, x, bottom-y, GR_LFB_SRC_FMT_8888,
+ n, 1, 0, (void *) data );
+ }
+}
+
+
+static void fxDDReadRGBASpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLubyte rgba[][4])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLushort data[MAX_WIDTH];
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadRGBASpan(...)\n");
+ }
+
+ assert(n < MAX_WIDTH);
+
+ grLfbReadRegion( fxMesa->currentFB, x, bottom-y, n, 1, 0, data);
+ for (i=0;i<n;i++) {
+#if FXMESA_USE_ARGB
+ rgba[i][RCOMP]=(data[i] & 0xF800) >> 8;
+ rgba[i][GCOMP]=(data[i] & 0x07E0) >> 3;
+ rgba[i][BCOMP]=(data[i] & 0x001F) << 3;
+#else
+ rgba[i][RCOMP]=(data[i] & 0x001f) << 3;
+ rgba[i][GCOMP]=(data[i] & 0x07e0) >> 3;
+ rgba[i][BCOMP]=(data[i] & 0xf800) >> 8;
+#endif
+ rgba[i][ACOMP]=255;
+ }
+
+}
+
+/************************************************************************/
+/***** Pixel functions *****/
+/************************************************************************/
+
+static void fxDDWriteRGBAPixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteRGBAPixels(...)\n");
+ }
+
+ for(i=0;i<n;i++)
+ if(mask[i])
+ LFB_WRITE_SPAN_MESA(fxMesa->currentFB,x[i],bottom-y[i],
+ /*GR_LFB_SRC_FMT_8888,*/1,/*1,*/0,(void *)rgba[i]);
+}
+
+static void fxDDWriteMonoRGBAPixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteMonoRGBAPixels(...)\n");
+ }
+
+ for(i=0;i<n;i++)
+ if(mask[i])
+ FX_grLfbWriteRegion(fxMesa->currentFB,x[i],bottom-y[i],
+ GR_LFB_SRC_FMT_8888,1,1,0,(void *) &fxMesa->color);
+}
+
+static void fxDDReadRGBAPixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLushort data;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadRGBAPixels(...)\n");
+ }
+
+ for(i=0;i<n;i++)
+ if(mask[i]) {
+ grLfbReadRegion(fxMesa->currentFB,x[i],bottom-y[i],1,1,0,&data);
+ #if FXMESA_USE_ARGB
+ rgba[i][RCOMP]=(data & 0xF800) >> 8;
+ rgba[i][GCOMP]=(data & 0x07E0) >> 3;
+ rgba[i][BCOMP]=(data & 0x001F) >> 8;
+ #else
+ rgba[i][RCOMP]=(data & 0x001f) << 3;
+ rgba[i][GCOMP]=(data & 0x07e0) >> 3;
+ rgba[i][BCOMP]=(data & 0xf800) >> 8;
+ #endif
+ /* the alpha value should be read from the auxiliary buffer when required */
+
+ rgba[i][ACOMP]=255;
+ }
+}
+
+/************************************************************************/
+/***** Depth functions *****/
+/************************************************************************/
+
+void fxDDReadDepthSpanFloat(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLfloat depth[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLushort data[MAX_WIDTH];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadDepthSpanFloat(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,data);
+
+ /*
+ convert the read values to float values [0.0 .. 1.0].
+ */
+ for(i=0;i<n;i++)
+ depth[i]=data[i]/65535.0f;
+}
+
+void fxDDReadDepthSpanInt(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadDepthSpanInt(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,depth);
+}
+
+GLuint fxDDDepthTestSpanGeneric(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, const GLdepth z[],
+ GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLushort depthdata[MAX_WIDTH];
+ GLdepth *zptr=depthdata;
+ GLubyte *m=mask;
+ GLuint i;
+ GLuint passed=0;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDDepthTestSpanGeneric(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,depthdata);
+
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] < *zptr) {
+ /* pass */
+ *zptr = z[i];
+ passed++;
+ } else {
+ /* fail */
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] < *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] <= *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] <= *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] >= *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] >= *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] > *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] > *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] != *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] != *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] == *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m =0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] == *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m =0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ *zptr = z[i];
+ passed++;
+ }
+ }
+ } else {
+ /* Don't update Z buffer or mask */
+ passed = n;
+ }
+ break;
+ case GL_NEVER:
+ for (i=0;i<n;i++) {
+ mask[i] = 0;
+ }
+ break;
+ default:
+ ;
+ } /*switch*/
+
+ if(passed)
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,GR_LFB_SRC_FMT_ZA16,n,1,0,depthdata);
+
+ return passed;
+}
+
+void fxDDDepthTestPixelsGeneric(GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLdepth zval;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDDepthTestPixelsGeneric(...)\n");
+ }
+
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] < zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] < zval) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] <= zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] <= zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] >= zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] >= zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] > zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] > zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] != zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] != zval) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] == zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] == zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ }
+ }
+ } else {
+ /* Don't update Z buffer or mask */
+ }
+ break;
+ case GL_NEVER:
+ /* depth test never passes */
+ for (i=0;i<n;i++) {
+ mask[i] = 0;
+ }
+ break;
+ default:
+ ;
+ } /*switch*/
+}
+
+/************************************************************************/
+
+
+void fxSetupDDSpanPointers(GLcontext *ctx)
+{
+ ctx->Driver.WriteRGBASpan =fxDDWriteRGBASpan;
+ ctx->Driver.WriteRGBSpan =fxDDWriteRGBSpan;
+ ctx->Driver.WriteMonoRGBASpan =fxDDWriteMonoRGBASpan;
+ ctx->Driver.WriteRGBAPixels =fxDDWriteRGBAPixels;
+ ctx->Driver.WriteMonoRGBAPixels =fxDDWriteMonoRGBAPixels;
+
+ ctx->Driver.WriteCI8Span =NULL;
+ ctx->Driver.WriteCI32Span =NULL;
+ ctx->Driver.WriteMonoCISpan =NULL;
+ ctx->Driver.WriteCI32Pixels =NULL;
+ ctx->Driver.WriteMonoCIPixels =NULL;
+
+ ctx->Driver.ReadRGBASpan =fxDDReadRGBASpan;
+ ctx->Driver.ReadRGBAPixels =fxDDReadRGBAPixels;
+
+ ctx->Driver.ReadCI32Span =NULL;
+ ctx->Driver.ReadCI32Pixels =NULL;
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_span(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxddtex.c b/src/mesa/drivers/glide/fxddtex.c
new file mode 100644
index 0000000000..05ef77570c
--- /dev/null
+++ b/src/mesa/drivers/glide/fxddtex.c
@@ -0,0 +1,1299 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxddtex.c - 3Dfx VooDoo Texture mapping functions
+*/
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+
+/************************************************************************/
+/*************************** Texture Mapping ****************************/
+/************************************************************************/
+
+static void fxTexInvalidate(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ fxTMMoveOutTM(fxMesa,tObj); /* TO DO: SLOW but easy to write */
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+ ti->validated=GL_FALSE;
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+static tfxTexInfo *fxAllocTexObjData(fxMesaContext fxMesa)
+{
+ tfxTexInfo *ti;
+ int i;
+
+ if(!(ti=malloc(sizeof(tfxTexInfo)))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ ti->validated=GL_FALSE;
+ ti->tmi.isInTM=GL_FALSE;
+
+ ti->tmi.whichTMU=FX_TMU_NONE;
+
+ ti->tmi.tm[FX_TMU0]=NULL;
+ ti->tmi.tm[FX_TMU1]=NULL;
+
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->maxFilt=GR_TEXTUREFILTER_BILINEAR;
+
+ ti->sClamp=GR_TEXTURECLAMP_WRAP;
+ ti->tClamp=GR_TEXTURECLAMP_WRAP;
+
+ if(fxMesa->haveTwoTMUs) {
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->LODblend=FXTRUE;
+ } else {
+ ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend=FXFALSE;
+ }
+
+ for(i=0;i<MAX_TEXTURE_LEVELS;i++) {
+ ti->tmi.mipmapLevel[i].used=GL_FALSE;
+ ti->tmi.mipmapLevel[i].data=NULL;
+ }
+
+ return ti;
+}
+
+void fxDDTexBind(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexBind(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ fxMesa->texBindNumber++;
+ ti->tmi.lastTimeUsed=fxMesa->texBindNumber;
+
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void fxDDTexEnv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ if(param)
+ fprintf(stderr,"fxmesa: texenv(%x,%x)\n",pname,(GLint)(*param));
+ else
+ fprintf(stderr,"fxmesa: texenv(%x)\n",pname);
+ }
+
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void fxDDTexParam(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLenum param=(GLenum)(GLint)params[0];
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexParam(%d,%x,%x,%x)\n",tObj->Name,(GLuint)tObj->DriverData,pname,param);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ switch(pname) {
+
+ case GL_TEXTURE_MIN_FILTER:
+ switch(param) {
+ case GL_NEAREST:
+ ti->mmMode=GR_MIPMAP_DISABLE;
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_LINEAR:
+ ti->mmMode=GR_MIPMAP_DISABLE;
+ ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ if(fxMesa->haveTwoTMUs) {
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->LODblend=FXTRUE;
+ } else {
+ ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend=FXFALSE;
+ }
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if(fxMesa->haveTwoTMUs) {
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->LODblend=FXTRUE;
+ } else {
+ ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend=FXFALSE;
+ }
+ ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
+ break;
+ default:
+ break;
+ }
+ fxTexInvalidate(ctx,tObj);
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ switch(param) {
+ case GL_NEAREST:
+ ti->maxFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ case GL_LINEAR:
+ ti->maxFilt=GR_TEXTUREFILTER_BILINEAR;
+ break;
+ default:
+ break;
+ }
+ fxTexInvalidate(ctx,tObj);
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ switch(param) {
+ case GL_CLAMP:
+ ti->sClamp=GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->sClamp=GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+
+ case GL_TEXTURE_WRAP_T:
+ switch(param) {
+ case GL_CLAMP:
+ ti->tClamp=GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->tClamp=GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ /* TO DO */
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ fxTexInvalidate(ctx,tObj);
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ fxTexInvalidate(ctx,tObj);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void fxDDTexDel(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexDel(%d,%x)\n",tObj->Name,(GLuint)ti);
+ }
+
+ if(!ti)
+ return;
+
+ fxTMFreeTexture(fxMesa,tObj);
+
+ free(ti);
+ tObj->DriverData=NULL;
+
+ ctx->NewState|=NEW_TEXTURING;
+}
+
+void fxDDTexPalette(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ int i;
+ FxU32 r,g,b,a;
+ tfxTexInfo *ti;
+
+ if(tObj) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexPalette(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData);
+ }
+
+ if(tObj->PaletteFormat!=GL_RGBA) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n");
+#endif
+ return;
+ }
+
+ if(tObj->PaletteSize>256) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n");
+#endif
+ return;
+ }
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ for(i=0;i<tObj->PaletteSize;i++) {
+ r=tObj->Palette[i*4];
+ g=tObj->Palette[i*4+1];
+ b=tObj->Palette[i*4+2];
+ a=tObj->Palette[i*4+3];
+ ti->palette.data[i]=(a<<24)|(r<<16)|(g<<8)|b;
+ }
+
+ fxTexInvalidate(ctx,tObj);
+ } else {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexPalette(global)\n");
+ }
+ if(ctx->Texture.PaletteFormat!=GL_RGBA) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n");
+#endif
+ return;
+ }
+
+ if(ctx->Texture.PaletteSize>256) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n");
+#endif
+ return;
+ }
+
+ for(i=0;i<ctx->Texture.PaletteSize;i++) {
+ r=ctx->Texture.Palette[i*4];
+ g=ctx->Texture.Palette[i*4+1];
+ b=ctx->Texture.Palette[i*4+2];
+ a=ctx->Texture.Palette[i*4+3];
+ fxMesa->glbPalette.data[i]=(a<<24)|(r<<16)|(g<<8)|b;
+ }
+
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+void fxDDTexUseGlbPalette(GLcontext *ctx, GLboolean state)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexUseGlbPalette(%d)\n",state);
+ }
+
+ if(state) {
+ fxMesa->haveGlobalPaletteTexture=1;
+
+ FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(fxMesa->glbPalette));
+ if (fxMesa->haveTwoTMUs)
+ FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(fxMesa->glbPalette));
+ } else {
+ fxMesa->haveGlobalPaletteTexture=0;
+
+ if((ctx->Texture.Unit[0].Current==ctx->Texture.Unit[0].CurrentD[2]) &&
+ (ctx->Texture.Unit[0].Current!=NULL)) {
+ struct gl_texture_object *tObj=ctx->Texture.Unit[0].Current;
+ tfxTexInfo *ti;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ fxTexInvalidate(ctx,tObj);
+ }
+ }
+}
+
+static int logbase2(int n)
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ if (n<0) {
+ return -1;
+ }
+
+ while (n > i) {
+ i *= 2;
+ log2++;
+ }
+ if (i != n) {
+ return -1;
+ }
+ else {
+ return log2;
+ }
+}
+
+/* Need different versions for different cpus.
+ */
+#define INT_TRICK(l2) (0x800000 * l2)
+
+
+int fxTexGetInfo(int w, int h, GrLOD_t *lodlevel, GrAspectRatio_t *ar,
+ float *sscale, float *tscale,
+ int *i_sscale, int *i_tscale,
+ int *wscale, int *hscale)
+{
+
+ static GrLOD_t lod[9]={GR_LOD_256,GR_LOD_128,GR_LOD_64,GR_LOD_32,
+ GR_LOD_16,GR_LOD_8,GR_LOD_4,GR_LOD_2,GR_LOD_1};
+
+ int logw,logh,ws,hs;
+ GrLOD_t l;
+ GrAspectRatio_t aspectratio;
+ float s,t;
+ int is,it;
+
+ logw=logbase2(w);
+ logh=logbase2(h);
+
+ switch(logw-logh) {
+ case 0:
+ aspectratio=GR_ASPECT_1x1;
+ l=lod[8-logw];
+ s=t=256.0f;
+ is=it=INT_TRICK(8);
+ ws=hs=1;
+ break;
+ case 1:
+ aspectratio=GR_ASPECT_2x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=128.0f;
+ is=INT_TRICK(8);it=INT_TRICK(7);
+ ws=1;
+ hs=1;
+ break;
+ case 2:
+ aspectratio=GR_ASPECT_4x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=64.0f;
+ is=INT_TRICK(8);it=INT_TRICK(6);
+ ws=1;
+ hs=1;
+ break;
+ case 3:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=1;
+ break;
+ case 4:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=2;
+ break;
+ case 5:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=4;
+ break;
+ case 6:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=8;
+ break;
+ case 7:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=16;
+ break;
+ case 8:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=32;
+ break;
+ case -1:
+ aspectratio=GR_ASPECT_1x2;
+ l=lod[8-logh];
+ s=128.0f;
+ t=256.0f;
+ is=INT_TRICK(7);it=INT_TRICK(8);
+ ws=1;
+ hs=1;
+ break;
+ case -2:
+ aspectratio=GR_ASPECT_1x4;
+ l=lod[8-logh];
+ s=64.0f;
+ t=256.0f;
+ is=INT_TRICK(6);it=INT_TRICK(8);
+ ws=1;
+ hs=1;
+ break;
+ case -3:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=1;
+ hs=1;
+ break;
+ case -4:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=2;
+ hs=1;
+ break;
+ case -5:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=4;
+ hs=1;
+ break;
+ case -6:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=8;
+ hs=1;
+ break;
+ case -7:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=16;
+ hs=1;
+ break;
+ case -8:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=32;
+ hs=1;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ if(lodlevel)
+ (*lodlevel)=l;
+
+ if(ar)
+ (*ar)=aspectratio;
+
+ if(sscale)
+ (*sscale)=s;
+
+ if(tscale)
+ (*tscale)=t;
+
+ if(wscale)
+ (*wscale)=ws;
+
+ if(hscale)
+ (*hscale)=hs;
+
+ if (i_sscale)
+ *i_sscale = is;
+
+ if (i_tscale)
+ *i_tscale = it;
+
+
+ return 1;
+}
+
+void fxTexGetFormat(GLenum glformat, GrTextureFormat_t *tfmt, GLint *ifmt)
+{
+ switch(glformat) {
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_INTENSITY_8;
+ if(ifmt)
+ (*ifmt)=GL_LUMINANCE;
+ break;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ALPHA_INTENSITY_88;
+ if(ifmt)
+ (*ifmt)=GL_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ALPHA_8;
+ if(ifmt)
+ (*ifmt)=GL_INTENSITY;
+ break;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ALPHA_8;
+ if(ifmt)
+ (*ifmt)=GL_ALPHA;
+ break;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_RGB_565;
+ if(ifmt)
+ (*ifmt)=GL_RGB;
+ break;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ARGB_4444;
+ if(ifmt)
+ (*ifmt)=GL_RGBA;
+ break;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_P_8;
+ if(ifmt)
+ (*ifmt)=GL_RGBA;
+ break;
+ default:
+ fprintf(stderr,"fx Driver: unsupported internalFormat in fxTexGetFormat()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+}
+
+static int fxIsTexSupported(GLenum target, GLint internalFormat,
+ const struct gl_texture_image *image)
+{
+ if(target!=GL_TEXTURE_2D)
+ return GL_FALSE;
+
+ switch(internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ if(image->Width>256)
+ return GL_FALSE;
+
+ if(image->Height>256)
+ return GL_FALSE;
+
+ if(!fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,
+ NULL,NULL))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static void fxTexBuildImageMap(const struct gl_texture_image *image,
+ GLint internalFormat, unsigned short **dest,
+ GLboolean *istranslate)
+{
+ unsigned short *src;
+ unsigned char *data;
+ int x,y,w,h,wscale,hscale,idx;
+
+ fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,
+ &wscale,&hscale);
+ w=image->Width*wscale;
+ h=image->Height*hscale;
+
+ data=image->Data;
+ switch(internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ /* Optimized for GLQuake */
+
+ if(wscale==hscale==1) {
+ (*istranslate)=GL_FALSE;
+
+ (*dest)=(unsigned short *)data;
+ } else {
+ unsigned char *srcb;
+
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned char)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ srcb=(unsigned char *)src;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale));
+ srcb[x+y*w]=data[idx];
+ }
+ }
+ break;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ if(wscale==hscale==1) {
+ int i=0;
+ int lenght=h*w;
+ unsigned short a,l;
+
+ while(i++<lenght) {
+ l=*data++;
+ a=*data++;
+
+ *src++=(a << 8) | l;
+ }
+ } else {
+ unsigned short a,l;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale))*2;
+ l=data[idx];
+ a=data[idx+1];
+
+ src[x+y*w]=(a << 8) | l;
+ }
+ }
+ break;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ if(wscale==hscale==1) {
+ int i=0;
+ int lenght=h*w;
+ unsigned short r,g,b;
+
+ while(i++<lenght) {
+ r=*data++;
+ g=*data++;
+ b=*data++;
+
+ *src++=((0xf8 & r) << (11-3)) |
+ ((0xfc & g) << (5-3+1)) |
+ ((0xf8 & b) >> 3);
+ }
+ } else {
+ unsigned short r,g,b;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale))*3;
+ r=data[idx];
+ g=data[idx+1];
+ b=data[idx+2];
+
+ src[x+y*w]=((0xf8 & r) << (11-3)) |
+ ((0xfc & g) << (5-3+1)) |
+ ((0xf8 & b) >> 3);
+ }
+ }
+ break;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ if(wscale==hscale==1) {
+ int i=0;
+ int lenght=h*w;
+ unsigned short r,g,b,a;
+
+ while(i++<lenght) {
+ r=*data++;
+ g=*data++;
+ b=*data++;
+ a=*data++;
+
+ *src++=((0xf0 & a) << 8) |
+ ((0xf0 & r) << 4) |
+ (0xf0 & g) |
+ ((0xf0 & b) >> 4);
+ }
+ } else {
+ unsigned short r,g,b,a;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale))*4;
+ r=data[idx];
+ g=data[idx+1];
+ b=data[idx+2];
+ a=data[idx+3];
+
+ src[x+y*w]=((0xf0 & a) << 8) |
+ ((0xf0 & r) << 4) |
+ (0xf0 & g) |
+ ((0xf0 & b) >> 4);
+ }
+ }
+ break;
+ default:
+ fprintf(stderr,"fx Driver: wrong internalFormat in texbuildimagemap()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+}
+
+void fxDDTexImg(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level, GLint internalFormat,
+ const struct gl_texture_image *image)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: (%d) fxDDTexImg(...,%d,%x,%d,%d...)\n",tObj->Name,
+ target,internalFormat,image->Width,image->Height);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ if(fxIsTexSupported(target,internalFormat,image)) {
+ GrTextureFormat_t gldformat;
+ tfxMipMapLevel *mml=&ti->tmi.mipmapLevel[level];
+
+ fxTexGetFormat(internalFormat,&gldformat,NULL);
+
+ if(mml->used) {
+ if((mml->glideFormat==gldformat) &&
+ (mml->width==image->Width) &&
+ (mml->height==image->Height)) {
+ fxTexBuildImageMap(image,internalFormat,&(mml->data),
+ &(mml->translated));
+
+ if(ti->validated && ti->tmi.isInTM)
+ fxTMReloadMipMapLevel(fxMesa,tObj,level);
+ else
+ fxTexInvalidate(ctx,tObj);
+
+ return;
+ } else {
+ if(mml->translated)
+ free(mml->data);
+ mml->data=NULL;
+ }
+ }
+
+ mml->glideFormat=gldformat;
+ mml->width=image->Width;
+ mml->height=image->Height;
+ mml->used=GL_TRUE;
+
+ fxTexBuildImageMap(image,internalFormat,&(mml->data),
+ &(mml->translated));
+
+ fxTexInvalidate(ctx,tObj);
+ }
+#ifndef FX_SILENT
+ else
+ fprintf(stderr,"fx Driver: unsupported texture in fxDDTexImg()\n");
+#endif
+}
+
+static void fxTexBuildSubImageMap(const struct gl_texture_image *image,
+ GLint internalFormat,
+ GLint xoffset, GLint yoffset, GLint width, GLint height,
+ unsigned short *destimg)
+{
+ fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,
+ NULL,NULL);
+
+ switch(internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ {
+
+ int y;
+ unsigned char *bsrc,*bdst;
+
+ bsrc=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset));
+ bdst=((unsigned char *)destimg)+(yoffset*image->Width+xoffset);
+
+ for(y=0;y<height;y++) {
+ MEMCPY(bdst,bsrc,width);
+ bsrc += image->Width;
+ bdst += image->Width;
+ }
+ }
+ break;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ {
+ int x,y;
+ unsigned char *src;
+ unsigned short *dst,a,l;
+ int simgw,dimgw;
+
+ src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*2);
+ dst=destimg+(yoffset*image->Width+xoffset);
+
+ simgw=(image->Width-width)*2;
+ dimgw=image->Width-width;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ l=*src++;
+ a=*src++;
+ *dst++=(a << 8) | l;
+ }
+
+ src += simgw;
+ dst += dimgw;
+ }
+ }
+ break;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ {
+ int x,y;
+ unsigned char *src;
+ unsigned short *dst,r,g,b;
+ int simgw,dimgw;
+
+ src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*3);
+ dst=destimg+(yoffset*image->Width+xoffset);
+
+ simgw=(image->Width-width)*3;
+ dimgw=image->Width-width;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ r=*src++;
+ g=*src++;
+ b=*src++;
+ *dst++=((0xf8 & r) << (11-3)) |
+ ((0xfc & g) << (5-3+1)) |
+ ((0xf8 & b) >> 3);
+ }
+
+ src += simgw;
+ dst += dimgw;
+ }
+ }
+ break;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ {
+ int x,y;
+ unsigned char *src;
+ unsigned short *dst,r,g,b,a;
+ int simgw,dimgw;
+
+ src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*4);
+ dst=destimg+(yoffset*image->Width+xoffset);
+
+ simgw=(image->Width-width)*4;
+ dimgw=image->Width-width;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ r=*src++;
+ g=*src++;
+ b=*src++;
+ a=*src++;
+ *dst++=((0xf0 & a) << 8) |
+ ((0xf0 & r) << 4) |
+ (0xf0 & g) |
+ ((0xf0 & b) >> 4);
+ }
+
+ src += simgw;
+ dst += dimgw;
+ }
+ }
+ break;
+ default:
+ fprintf(stderr,"fx Driver: wrong internalFormat in fxTexBuildSubImageMap()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+}
+
+
+void fxDDTexSubImg(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level,
+ GLint xoffset, GLint yoffset, GLint width, GLint height,
+ GLint internalFormat, const struct gl_texture_image *image)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+ GrTextureFormat_t gldformat;
+ int wscale,hscale;
+ tfxMipMapLevel *mml;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: (%d) fxDDTexSubImg(...,%d,%x,%d,%d...)\n",tObj->Name,
+ target,internalFormat,image->Width,image->Height);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ return;
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+ mml=&ti->tmi.mipmapLevel[level];
+
+ fxTexGetFormat(internalFormat,&gldformat,NULL);
+
+ if(mml->glideFormat!=gldformat) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: ti->info.format!=format in fxDDTexSubImg()\n");
+ }
+ fxDDTexImg(ctx,target,tObj,level,internalFormat,image);
+
+ return;
+ }
+
+ fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,&wscale,&hscale);
+
+ if((wscale!=1) || (hscale!=1)) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: (wscale!=1) || (hscale!=1) in fxDDTexSubImg()\n");
+ }
+ fxDDTexImg(ctx,target,tObj,level,internalFormat,image);
+
+ return;
+ }
+
+ if(mml->translated)
+ fxTexBuildSubImageMap(image,internalFormat,xoffset,yoffset,
+ width,height,mml->data);
+
+ if(ti->validated && ti->tmi.isInTM)
+ fxTMReloadSubMipMapLevel(fxMesa,tObj,level,yoffset,height);
+ else
+ fxTexInvalidate(ctx,tObj);
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_ddtex(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxdrv.h b/src/mesa/drivers/glide/fxdrv.h
new file mode 100644
index 0000000000..bb8f5b8761
--- /dev/null
+++ b/src/mesa/drivers/glide/fxdrv.h
@@ -0,0 +1,576 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxdrv.h - 3Dfx VooDoo driver types
+*/
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifndef FXDRV_H
+#define FXDRV_H
+
+/* If you comment out this define, a variable takes its place, letting
+ * you turn debugging on/off from the debugger.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+
+#if defined(__linux__)
+#include <signal.h>
+#endif
+
+#include "context.h"
+#include "macros.h"
+#include "matrix.h"
+#include "texture.h"
+#include "types.h"
+#include "vb.h"
+#include "xform.h"
+#include "clip.h"
+#include "vbrender.h"
+
+#include "GL/fxmesa.h"
+#include "fxglidew.h"
+/* use gl/gl.h GLAPI/GLAPIENTRY/GLCALLBACK in place of WINGDIAPI/APIENTRY/CALLBACK, */
+/* these are defined in mesa gl/gl.h - tjump@spgs.com */
+
+
+
+#if defined(MESA_DEBUG) && 0
+extern void fx_sanity_triangle( GrVertex *, GrVertex *, GrVertex * );
+#define grDrawTriangle fx_sanity_triangle
+#endif
+
+
+/* Define some shorter names for these things.
+ */
+#define XCOORD GR_VERTEX_X_OFFSET
+#define YCOORD GR_VERTEX_Y_OFFSET
+#define ZCOORD GR_VERTEX_OOZ_OFFSET
+#define OOWCOORD GR_VERTEX_OOW_OFFSET
+
+#define RCOORD GR_VERTEX_R_OFFSET
+#define GCOORD GR_VERTEX_G_OFFSET
+#define BCOORD GR_VERTEX_B_OFFSET
+#define ACOORD GR_VERTEX_A_OFFSET
+
+#define S0COORD GR_VERTEX_SOW_TMU0_OFFSET
+#define T0COORD GR_VERTEX_TOW_TMU0_OFFSET
+#define S1COORD GR_VERTEX_SOW_TMU1_OFFSET
+#define T1COORD GR_VERTEX_TOW_TMU1_OFFSET
+
+#define CLIP_XCOORD 0 /* normal place */
+#define CLIP_YCOROD 1 /* normal place */
+#define CLIP_ZCOORD 2 /* GR_VERTEX_Z_OFFSET */
+#define CLIP_WCOORD 3 /* GR_VERTEX_R_OFFSET */
+#define CLIP_GCOORD 4 /* normal place */
+#define CLIP_BCOORD 5 /* normal place */
+#define CLIP_RCOORD 6 /* GR_VERTEX_OOZ_OFFSET */
+#define CLIP_ACOORD 7 /* normal place */
+
+
+
+
+/* Should have size == 16 * sizeof(float).
+ */
+typedef struct {
+ GLfloat f[15]; /* Same layout as GrVertex */
+ GLubyte mask; /* Unsued */
+ GLubyte usermask; /* Unused */
+} fxVertex;
+
+
+
+
+#if defined(FXMESA_USE_ARGB)
+#define FXCOLOR4( c ) ( \
+ ( ((unsigned int)(c[3]))<<24 ) | \
+ ( ((unsigned int)(c[0]))<<16 ) | \
+ ( ((unsigned int)(c[1]))<<8 ) | \
+ ( (unsigned int)(c[2])) )
+
+#else
+#ifdef __i386__
+#define FXCOLOR4( c ) (* (int *)c)
+#else
+#define FXCOLOR4( c ) ( \
+ ( ((unsigned int)(c[3]))<<24 ) | \
+ ( ((unsigned int)(c[2]))<<16 ) | \
+ ( ((unsigned int)(c[1]))<<8 ) | \
+ ( (unsigned int)(c[0])) )
+#endif
+#endif
+
+#define FX_VB_COLOR(fxm, color) \
+do { \
+ if (sizeof(GLint) == 4*sizeof(GLubyte)) { \
+ if (fxm->constColor != *(GLuint*)color) { \
+ fxm->constColor = *(GLuint*)color; \
+ grConstantColorValue(FXCOLOR4(color)); \
+ } \
+ } else { \
+ grConstantColorValue(FXCOLOR4(color)); \
+ } \
+} while (0)
+
+#define GOURAUD(x) { \
+ GLubyte *col = VB->ColorPtr->data[(x)]; \
+ gWin[(x)].v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \
+ gWin[(x)].v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \
+ gWin[(x)].v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \
+ gWin[(x)].v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \
+}
+
+#define GOURAUD2(v, c) { \
+ GLubyte *col = c; \
+ v->r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \
+ v->g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \
+ v->b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \
+ v->a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \
+}
+
+
+/* Mergable items first
+ */
+#define SETUP_RGBA 0x1
+#define SETUP_TMU0 0x2
+#define SETUP_TMU1 0x4
+#define SETUP_XY 0x8
+#define SETUP_Z 0x10
+#define SETUP_W 0x20
+
+#define MAX_MERGABLE 0x8
+
+
+#define FX_NUM_TMU 2
+
+#define FX_TMU0 GR_TMU0
+#define FX_TMU1 GR_TMU1
+#define FX_TMU_SPLIT 98
+#define FX_TMU_BOTH 99
+#define FX_TMU_NONE 100
+
+/* Used for fxMesa->lastUnitsMode */
+
+#define FX_UM_NONE 0x00000000
+
+#define FX_UM_E0_REPLACE 0x00000001
+#define FX_UM_E0_MODULATE 0x00000002
+#define FX_UM_E0_DECAL 0x00000004
+#define FX_UM_E0_BLEND 0x00000008
+
+#define FX_UM_E1_REPLACE 0x00000010
+#define FX_UM_E1_MODULATE 0x00000020
+#define FX_UM_E1_DECAL 0x00000040
+#define FX_UM_E1_BLEND 0x00000080
+
+#define FX_UM_E_ENVMODE 0x000000ff
+
+#define FX_UM_E0_ALPHA 0x00000100
+#define FX_UM_E0_LUMINANCE 0x00000200
+#define FX_UM_E0_LUMINANCE_ALPHA 0x00000400
+#define FX_UM_E0_INTENSITY 0x00000800
+#define FX_UM_E0_RGB 0x00001000
+#define FX_UM_E0_RGBA 0x00002000
+
+#define FX_UM_E1_ALPHA 0x00004000
+#define FX_UM_E1_LUMINANCE 0x00008000
+#define FX_UM_E1_LUMINANCE_ALPHA 0x00010000
+#define FX_UM_E1_INTENSITY 0x00020000
+#define FX_UM_E1_RGB 0x00040000
+#define FX_UM_E1_RGBA 0x00080000
+
+#define FX_UM_E_IFMT 0x000fff00
+
+#define FX_UM_COLOR_ITERATED 0x00100000
+#define FX_UM_COLOR_CONSTANT 0x00200000
+#define FX_UM_ALPHA_ITERATED 0x00400000
+#define FX_UM_ALPHA_CONSTANT 0x00800000
+
+typedef void (*tfxRenderVBFunc)(GLcontext *);
+
+typedef struct tfxTMFreeListNode {
+ struct tfxTMFreeListNode *next;
+ FxU32 startAddress, endAddress;
+} tfxTMFreeNode;
+
+typedef struct tfxTMAllocListNode {
+ struct tfxTMAllocListNode *next;
+ FxU32 startAddress, endAddress;
+ struct gl_texture_object *tObj;
+} tfxTMAllocNode;
+
+typedef struct {
+ GLsizei width, height;
+ GLint glideFormat;
+
+ unsigned short *data;
+ GLboolean translated, used;
+} tfxMipMapLevel;
+
+typedef struct {
+ GLuint lastTimeUsed;
+
+ FxU32 whichTMU;
+
+ tfxTMAllocNode *tm[FX_NUM_TMU];
+
+ tfxMipMapLevel mipmapLevel[MAX_TEXTURE_LEVELS];
+ GLboolean isInTM;
+} tfxTMInfo;
+
+typedef struct {
+ tfxTMInfo tmi;
+
+ GLint minLevel, maxLevel;
+ GLint baseLevelInternalFormat;
+
+ GrTexInfo info;
+
+ GrTextureFilterMode_t minFilt;
+ GrTextureFilterMode_t maxFilt;
+ FxBool LODblend;
+
+ GrTextureClampMode_t sClamp;
+ GrTextureClampMode_t tClamp;
+
+ GrMipMapMode_t mmMode;
+
+ GLfloat sScale, tScale;
+ GLint int_sScale, int_tScale; /* x86 floating point trick for
+ * multiplication by powers of 2.
+ * Used in fxfasttmp.h
+ */
+
+ GuTexPalette palette;
+
+ GLboolean fixedPalette;
+ GLboolean validated;
+} tfxTexInfo;
+
+typedef struct {
+ GLuint swapBuffer;
+ GLuint reqTexUpload;
+ GLuint texUpload;
+ GLuint memTexUpload;
+} tfxStats;
+
+
+typedef void (*tfxTriViewClipFunc)( struct vertex_buffer *VB,
+ GLuint v[],
+ GLubyte mask );
+
+typedef void (*tfxTriClipFunc)( struct vertex_buffer *VB,
+ GLuint v[],
+ GLuint mask );
+
+
+typedef void (*tfxLineClipFunc)( struct vertex_buffer *VB,
+ GLuint v1, GLuint v2,
+ GLubyte mask );
+
+
+extern tfxTriViewClipFunc fxTriViewClipTab[0x8];
+extern tfxTriClipFunc fxTriClipStrideTab[0x8];
+extern tfxLineClipFunc fxLineClipTab[0x8];
+
+typedef struct {
+ /* Alpha test */
+
+ GLboolean alphaTestEnabled;
+ GrCmpFnc_t alphaTestFunc;
+ GrAlpha_t alphaTestRefValue;
+
+ /* Blend function */
+
+ GLboolean blendEnabled;
+ GrAlphaBlendFnc_t blendSrcFuncRGB;
+ GrAlphaBlendFnc_t blendDstFuncRGB;
+ GrAlphaBlendFnc_t blendSrcFuncAlpha;
+ GrAlphaBlendFnc_t blendDstFuncAlpha;
+
+ /* Depth test */
+
+ GLboolean depthTestEnabled;
+ GLboolean depthMask;
+ GrCmpFnc_t depthTestFunc;
+} tfxUnitsState;
+
+
+/* Flags for render_index.
+ */
+#define FX_OFFSET 0x1
+#define FX_TWOSIDE 0x2
+#define FX_FRONT_BACK 0x4
+#define FX_FLAT 0x8
+#define FX_ANTIALIAS 0x10
+#define FX_FALLBACK 0x20
+
+
+/* Flags for fxMesa->new_state
+ */
+#define FX_NEW_TEXTURING 0x1
+#define FX_NEW_BLEND 0x2
+#define FX_NEW_ALPHA 0x4
+#define FX_NEW_DEPTH 0x8
+#define FX_NEW_FOG 0x10
+#define FX_NEW_SCISSOR 0x20
+#define FX_NEW_COLOR_MASK 0x40
+#define FX_NEW_CULL 0x80
+
+/* FX struct stored in VB->driver_data.
+ */
+struct tfxMesaVertexBuffer {
+ GLvector1ui clipped_elements;
+
+ fxVertex *verts;
+ fxVertex *last_vert;
+ void *vert_store;
+#if defined(FX_GLIDE3)
+ GrVertex **triangle_b; /* Triangle buffer */
+ GrVertex **strips_b; /* Strips buffer */
+#endif
+
+ GLuint size;
+};
+
+#define FX_DRIVER_DATA(vb) ((struct tfxMesaVertexBuffer *)((vb)->driver_data))
+#define FX_CONTEXT(ctx) ((struct tfxMesaContext *)((ctx)->DriverCtx))
+#define FX_TEXTURE_DATA(t) ((tfxTexInfo *) ((t)->Current->DriverData))
+
+struct tfxMesaContext {
+ GuTexPalette glbPalette;
+
+ GLcontext *glCtx; /* the core Mesa context */
+ GLvisual *glVis; /* describes the color buffer */
+ GLframebuffer *glBuffer; /* the ancillary buffers */
+
+ GLint board; /* the board used for this context */
+ GLint width, height; /* size of color buffer */
+
+ GrBuffer_t currentFB;
+
+ GrColor_t color;
+ GrColor_t clearC;
+ GrAlpha_t clearA;
+ GLuint constColor;
+
+ tfxUnitsState unitsState;
+ tfxUnitsState restoreUnitsState; /* saved during multipass */
+
+
+ GLuint tmu_source[FX_NUM_TMU];
+ GLuint tex_dest[MAX_TEXTURE_UNITS];
+ GLuint setupindex;
+ GLuint partial_setup_index;
+ GLuint setupdone;
+ GLuint mergeindex;
+ GLuint mergeinputs;
+ GLuint render_index;
+ GLuint last_tri_caps;
+ GLuint stw_hint_state; /* for grHints */
+ GLuint is_in_hardware;
+ GLuint new_state;
+ GLuint using_fast_path, passes, multipass;
+
+ tfxLineClipFunc clip_line;
+ tfxTriClipFunc clip_tri_stride;
+ tfxTriViewClipFunc view_clip_tri;
+
+
+ /* Texture Memory Manager Data */
+
+ GLuint texBindNumber;
+ GLint tmuSrc;
+ GLuint lastUnitsMode;
+ GLuint freeTexMem[FX_NUM_TMU];
+ tfxTMFreeNode *tmFree[FX_NUM_TMU];
+ tfxTMAllocNode *tmAlloc[FX_NUM_TMU];
+
+ GLenum fogTableMode;
+ GLfloat fogDensity;
+ GrFog_t *fogTable;
+
+ /* Acc. functions */
+
+ points_func PointsFunc;
+ line_func LineFunc;
+ triangle_func TriangleFunc;
+ quad_func QuadFunc;
+
+ render_func **RenderVBTables;
+
+ tfxStats stats;
+
+ void *state;
+
+ /* Options */
+
+ GLboolean verbose;
+ GLboolean haveTwoTMUs; /* True if we really have 2 tmu's */
+ GLboolean emulateTwoTMUs; /* True if we present 2 tmu's to mesa. */
+ GLboolean haveAlphaBuffer;
+ GLboolean haveDoubleBuffer;
+ GLboolean haveGlobalPaletteTexture;
+ GLint swapInterval;
+ GLint maxPendingSwapBuffers;
+
+ FX_GrContext_t glideContext;
+};
+
+typedef void (*tfxSetupFunc)(struct vertex_buffer *, GLuint, GLuint);
+
+extern GrHwConfiguration glbHWConfig;
+extern int glbCurrentBoard;
+
+extern void fxSetupFXUnits(GLcontext *);
+extern void fxSetupDDPointers(GLcontext *);
+extern void fxDDSetNearFar(GLcontext *, GLfloat, GLfloat);
+
+extern void fxDDSetupInit();
+extern void fxDDCvaInit();
+extern void fxDDTrifuncInit();
+extern void fxDDFastPathInit();
+
+extern void fxDDChooseRenderState( GLcontext *ctx );
+
+extern void fxRenderClippedLine( struct vertex_buffer *VB,
+ GLuint v1, GLuint v2 );
+
+extern void fxRenderClippedTriangle( struct vertex_buffer *VB,
+ GLuint n, GLuint vlist[] );
+
+
+extern tfxSetupFunc fxDDChooseSetupFunction(GLcontext *);
+
+extern points_func fxDDChoosePointsFunction(GLcontext *);
+extern line_func fxDDChooseLineFunction(GLcontext *);
+extern triangle_func fxDDChooseTriangleFunction(GLcontext *);
+extern quad_func fxDDChooseQuadFunction(GLcontext *);
+extern render_func **fxDDChooseRenderVBTables(GLcontext *);
+
+extern void fxDDRenderInit(GLcontext *);
+extern void fxDDClipInit();
+
+extern void fxUpdateDDSpanPointers(GLcontext *);
+extern void fxSetupDDSpanPointers(GLcontext *);
+
+extern void fxDDBufferSize(GLcontext *, GLuint *, GLuint *);
+
+extern void fxDDTexEnv(GLcontext *, GLenum, const GLfloat *);
+extern void fxDDTexImg(GLcontext *, GLenum, struct gl_texture_object *,
+ GLint, GLint, const struct gl_texture_image *);
+extern void fxDDTexParam(GLcontext *, GLenum, struct gl_texture_object *,
+ GLenum, const GLfloat *);
+extern void fxDDTexBind(GLcontext *, GLenum, struct gl_texture_object *);
+extern void fxDDTexDel(GLcontext *, struct gl_texture_object *);
+extern void fxDDTexPalette(GLcontext *, struct gl_texture_object *);
+extern void fxDDTexuseGlbPalette(GLcontext *, GLboolean);
+extern void fxDDTexSubImg(GLcontext *, GLenum, struct gl_texture_object *, GLint,
+ GLint, GLint, GLint, GLint, GLint, const struct gl_texture_image *);
+extern void fxDDTexUseGlbPalette(GLcontext *, GLboolean);
+
+extern void fxDDEnable(GLcontext *, GLenum, GLboolean);
+extern void fxDDAlphaFunc(GLcontext *, GLenum, GLclampf);
+extern void fxDDBlendFunc(GLcontext *, GLenum, GLenum);
+extern void fxDDDepthMask(GLcontext *, GLboolean);
+extern void fxDDDepthFunc(GLcontext *, GLenum);
+
+extern void fxDDRegisterVB( struct vertex_buffer *VB );
+extern void fxDDUnregisterVB( struct vertex_buffer *VB );
+extern void fxDDResizeVB( struct tfxMesaVertexBuffer *fvb, GLuint size );
+
+extern void fxDDCheckMergeAndRender( GLcontext *ctx,
+ struct gl_pipeline_stage *d );
+
+extern void fxDDMergeAndRender( struct vertex_buffer *VB );
+
+extern void fxDDCheckPartialRasterSetup( GLcontext *ctx,
+ struct gl_pipeline_stage *d );
+
+extern void fxDDPartialRasterSetup( struct vertex_buffer *VB );
+
+extern void fxDDDoRasterSetup( struct vertex_buffer *VB );
+
+extern GLuint fxDDRegisterPipelineStages( struct gl_pipeline_stage *out,
+ const struct gl_pipeline_stage *in,
+ GLuint nr );
+
+extern GLboolean fxDDBuildPrecalcPipeline( GLcontext *ctx );
+
+extern void fxDDOptimizePrecalcPipeline( GLcontext *ctx,
+ struct gl_pipeline *pipe );
+
+extern void fxDDRenderElementsDirect( struct vertex_buffer *VB );
+extern void fxDDRenderVBIndirectDirect( struct vertex_buffer *VB );
+
+extern void fxDDInitExtensions( GLcontext *ctx );
+
+extern void fxTMInit(fxMesaContext);
+extern void fxTMClose(fxMesaContext);
+extern void fxTMMoveInTM(fxMesaContext, struct gl_texture_object *, GLint);
+extern void fxTMMoveOutTM(fxMesaContext, struct gl_texture_object *);
+extern void fxTMFreeTexture(fxMesaContext, struct gl_texture_object *);
+extern void fxTMReloadMipMapLevel(fxMesaContext, struct gl_texture_object *, GLint);
+extern void fxTMReloadSubMipMapLevel(fxMesaContext, struct gl_texture_object *,
+ GLint, GLint, GLint);
+
+extern void fxTexGetFormat(GLenum, GrTextureFormat_t *, GLint *);
+extern int fxTexGetInfo(int, int, GrLOD_t *, GrAspectRatio_t *,
+ float *, float *, int *, int *, int *, int *);
+
+extern void fxDDScissor( GLcontext *ctx,
+ GLint x, GLint y, GLsizei w, GLsizei h );
+extern void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params );
+extern GLboolean fxDDColorMask(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a );
+
+extern GLuint fxDDDepthTestSpanGeneric(GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLdepth z[],
+ GLubyte mask[]);
+
+extern void fxDDDepthTestPixelsGeneric(GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[]);
+
+extern void fxDDReadDepthSpanFloat(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLfloat depth[]);
+
+extern void fxDDReadDepthSpanInt(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[]);
+
+
+extern void fxDDFastPath( struct vertex_buffer *VB );
+
+extern void fxDDShadeModel(GLcontext *ctx, GLenum mode);
+
+extern void fxDDCullFace(GLcontext *ctx, GLenum mode);
+extern void fxDDFrontFace(GLcontext *ctx, GLenum mode);
+
+
+
+
+#endif
diff --git a/src/mesa/drivers/glide/fxglidew.c b/src/mesa/drivers/glide/fxglidew.c
new file mode 100644
index 0000000000..3ced928f49
--- /dev/null
+++ b/src/mesa/drivers/glide/fxglidew.c
@@ -0,0 +1,247 @@
+/* $Id: fxglidew.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+#include "glide.h"
+#include "fxglidew.h"
+#include "fxdrv.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+FxI32 FX_grGetInteger(FxU32 pname)
+{
+#if !defined(FX_GLIDE3)
+ switch (pname)
+ {
+ case FX_FOG_TABLE_ENTRIES:
+ return GR_FOG_TABLE_SIZE;
+ case FX_GLIDE_STATE_SIZE:
+ return sizeof(GrState);
+ case FX_LFB_PIXEL_PIPE:
+ return FXFALSE;
+ case FX_PENDING_BUFFERSWAPS:
+ return grBufferNumPending();
+ default:
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n");
+ return -1;
+ }
+ }
+#else
+ FxU32 grname;
+ FxI32 result;
+
+ switch (pname)
+ {
+ case FX_FOG_TABLE_ENTRIES:
+ case FX_GLIDE_STATE_SIZE:
+ case FX_LFB_PIXEL_PIPE:
+ case FX_PENDING_BUFFERSWAPS:
+ grname = pname;
+ break;
+ default:
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n");
+ return -1;
+ }
+ }
+
+ grGet(grname,4,&result);
+ return result;
+#endif
+}
+
+
+
+#if defined(FX_GLIDE3)
+
+void FX_grGammaCorrectionValue(float val)
+{
+ (void)val;
+/* ToDo */
+}
+
+void FX_grSstControl(int par)
+{
+ (void)par;
+ /* ToDo */
+}
+int FX_getFogTableSize(void)
+{
+ int result;
+ grGet(GR_FOG_TABLE_ENTRIES,sizeof(int),(void*)&result);
+ return result;
+}
+
+int FX_getGrStateSize(void)
+{
+ int result;
+ grGet(GR_GLIDE_STATE_SIZE,sizeof(int),(void*)&result);
+
+ return result;
+
+}
+int FX_grBufferNumPending()
+{
+ int result;
+ grGet(GR_PENDING_BUFFERSWAPS,sizeof(int),(void*)&result);
+
+ return result;
+}
+
+int FX_grSstScreenWidth()
+{
+ FxI32 result[4];
+
+ grGet(GR_VIEWPORT,sizeof(FxI32)*4,result);
+
+ return result[2];
+}
+
+int FX_grSstScreenHeight()
+{
+ FxI32 result[4];
+
+ grGet(GR_VIEWPORT,sizeof(FxI32)*4,result);
+
+ return result[3];
+}
+
+void FX_grGlideGetVersion(char *buf)
+{
+ strcpy(buf,grGetString(GR_VERSION));
+}
+
+void FX_grSstPerfStats(GrSstPerfStats_t *st)
+{
+ /* ToDo */
+ st->pixelsIn = 0;
+ st->chromaFail = 0;
+ st->zFuncFail = 0;
+ st->aFuncFail = 0;
+ st->pixelsOut = 0;
+}
+
+void FX_grAADrawLine(GrVertex *a,GrVertex *b)
+{
+ /* ToDo */
+ grDrawLine(a,b);
+}
+void FX_grAADrawPoint(GrVertex *a)
+{
+ grDrawPoint(a);
+}
+
+void FX_setupGrVertexLayout(void)
+{
+ grReset(GR_VERTEX_PARAMETER);
+
+ grCoordinateSpace(GR_WINDOW_COORDS);
+ grVertexLayout(GR_PARAM_XY, GR_VERTEX_X_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_RGB, GR_VERTEX_R_OFFSET << 2, GR_PARAM_ENABLE);
+ /* grVertexLayout(GR_PARAM_Z, GR_VERTEX_Z_OFFSET << 2, GR_PARAM_ENABLE); */
+ grVertexLayout(GR_PARAM_A, GR_VERTEX_A_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Q, GR_VERTEX_OOW_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Z, GR_VERTEX_OOZ_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_ST0, GR_VERTEX_SOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE);
+ grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+ grVertexLayout(GR_PARAM_Q1, GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+}
+
+void FX_grHints(GrHint_t hintType, FxU32 hintMask)
+{
+ switch(hintType) {
+ case GR_HINT_STWHINT:
+ {
+ if (hintMask & GR_STWHINT_W_DIFF_TMU0)
+ grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_Q0,GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE);
+
+ if (hintMask & GR_STWHINT_ST_DIFF_TMU1)
+ grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+
+ if (hintMask & GR_STWHINT_W_DIFF_TMU1)
+ grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+
+ }
+ }
+}
+int FX_grSstQueryHardware(GrHwConfiguration *config)
+{
+ int i,j;
+ int numFB;
+ grGet(GR_NUM_BOARDS,4,(void*)&(config->num_sst));
+ if (config->num_sst == 0)
+ return 0;
+ for (i = 0; i< config->num_sst; i++)
+ {
+ config->SSTs[i].type = GR_SSTTYPE_VOODOO;
+ grSstSelect(i);
+ grGet(GR_MEMORY_FB,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.fbRam));
+ config->SSTs[i].sstBoard.VoodooConfig.fbRam/= 1024*1024;
+
+ grGet(GR_NUM_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.nTexelfx));
+
+
+ grGet(GR_NUM_FB,4,(void*)&numFB);
+ if (numFB > 1)
+ config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXTRUE;
+ else
+ config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXFALSE;
+ for (j = 0; j < config->SSTs[i].sstBoard.VoodooConfig.nTexelfx; j++)
+ {
+ grGet(GR_MEMORY_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.tmuConfig[i].tmuRam));
+ }
+ }
+ return 1;
+}
+
+
+#endif
+#else
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_glidew(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxglidew.h b/src/mesa/drivers/glide/fxglidew.h
new file mode 100644
index 0000000000..17f395686c
--- /dev/null
+++ b/src/mesa/drivers/glide/fxglidew.h
@@ -0,0 +1,358 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * 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.
+ */
+#ifndef __FX_GLIDE_WARPER__
+#define __FX_GLIDE_WARPER__
+
+#include <glide.h>
+
+/*
+ * General context:
+ */
+#if !defined(FX_GLIDE3)
+ typedef FxU32 FX_GrContext_t; /* Not used in Glide2 */
+#else
+ typedef GrContext_t FX_GrContext_t;
+#endif
+
+/*
+ * Glide3 emulation on Glide2:
+ */
+#if !defined(FX_GLIDE3)
+ /* Constanst for FX_grGetInteger( ) */
+ #define FX_FOG_TABLE_ENTRIES 0x0004 /* The number of entries in the hardware fog table. */
+ #define FX_GLIDE_STATE_SIZE 0x0006 /* Size of buffer, in bytes, needed to save Glide state. */
+ #define FX_LFB_PIXEL_PIPE 0x0009 /* 1 if LFB writes can go through the 3D pixel pipe. */
+ #define FX_PENDING_BUFFERSWAPS 0x0014 /* The number of buffer swaps pending. */
+#else
+ #define FX_FOG_TABLE_ENTRIES GR_FOG_TABLE_ENTRIES
+ #define FX_GLIDE_STATE_SIZE GR_GLIDE_STATE_SIZE
+ #define FX_LFB_PIXEL_PIPE GR_LFB_PIXEL_PIPE
+ #define FX_PENDING_BUFFERSWAPS GR_PENDING_BUFFERSWAPS
+#endif
+
+/*
+ * Genral warper functions for Glide2/Glide3:
+ */
+extern FxI32 FX_grGetInteger(FxU32 pname);
+
+/*
+ * Glide2 emulation on Glide3:
+ */
+#if defined(FX_GLIDE3)
+
+#define GR_ASPECT_1x1 GR_ASPECT_LOG2_1x1
+#define GR_ASPECT_2x1 GR_ASPECT_LOG2_2x1
+#define GR_ASPECT_4x1 GR_ASPECT_LOG2_4x1
+#define GR_ASPECT_8x1 GR_ASPECT_LOG2_8x1
+#define GR_ASPECT_1x2 GR_ASPECT_LOG2_1x2
+#define GR_ASPECT_1x4 GR_ASPECT_LOG2_1x4
+#define GR_ASPECT_1x8 GR_ASPECT_LOG2_1x8
+
+#define GR_LOD_256 GR_LOD_LOG2_256
+#define GR_LOD_128 GR_LOD_LOG2_128
+#define GR_LOD_64 GR_LOD_LOG2_64
+#define GR_LOD_32 GR_LOD_LOG2_32
+#define GR_LOD_16 GR_LOD_LOG2_16
+#define GR_LOD_8 GR_LOD_LOG2_8
+#define GR_LOD_4 GR_LOD_LOG2_4
+#define GR_LOD_2 GR_LOD_LOG2_2
+#define GR_LOD_1 GR_LOD_LOG2_1
+
+#define GR_FOG_WITH_TABLE GR_FOG_WITH_TABLE_ON_Q
+
+typedef int GrSstType;
+
+#define MAX_NUM_SST 4
+
+#define GR_SSTTYPE_VOODOO 0
+#define GR_SSTTYPE_SST96 1
+#define GR_SSTTYPE_AT3D 2
+#define GR_SSTTYPE_Voodoo2 3
+
+typedef struct GrTMUConfig_St {
+ int tmuRev; /* Rev of Texelfx chip */
+ int tmuRam; /* 1, 2, or 4 MB */
+} GrTMUConfig_t;
+
+typedef struct GrVoodooConfig_St {
+ int fbRam; /* 1, 2, or 4 MB */
+ int fbiRev; /* Rev of Pixelfx chip */
+ int nTexelfx; /* How many texelFX chips are there? */
+ FxBool sliDetect; /* Is it a scan-line interleaved board? */
+ GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU]; /* Configuration of the Texelfx chips */
+} GrVoodooConfig_t;
+
+typedef struct GrSst96Config_St {
+ int fbRam; /* How much? */
+ int nTexelfx;
+ GrTMUConfig_t tmuConfig;
+} GrSst96Config_t;
+
+typedef GrVoodooConfig_t GrVoodoo2Config_t;
+
+typedef struct GrAT3DConfig_St {
+ int rev;
+} GrAT3DConfig_t;
+
+typedef struct {
+ int num_sst; /* # of HW units in the system */
+ struct {
+ GrSstType type; /* Which hardware is it? */
+ union SstBoard_u {
+ GrVoodooConfig_t VoodooConfig;
+ GrSst96Config_t SST96Config;
+ GrAT3DConfig_t AT3DConfig;
+ GrVoodoo2Config_t Voodoo2Config;
+ } sstBoard;
+ } SSTs[MAX_NUM_SST]; /* configuration for each board */
+} GrHwConfiguration;
+
+typedef FxU32 GrHint_t;
+#define GR_HINTTYPE_MIN 0
+#define GR_HINT_STWHINT 0
+
+typedef FxU32 GrSTWHint_t;
+#define GR_STWHINT_W_DIFF_FBI FXBIT(0)
+#define GR_STWHINT_W_DIFF_TMU0 FXBIT(1)
+#define GR_STWHINT_ST_DIFF_TMU0 FXBIT(2)
+#define GR_STWHINT_W_DIFF_TMU1 FXBIT(3)
+#define GR_STWHINT_ST_DIFF_TMU1 FXBIT(4)
+#define GR_STWHINT_W_DIFF_TMU2 FXBIT(5)
+#define GR_STWHINT_ST_DIFF_TMU2 FXBIT(6)
+
+#define GR_CONTROL_ACTIVATE 1
+#define GR_CONTROL_DEACTIVATE 0
+
+#define GrState void
+
+/*
+** move the vertex layout defintion to application
+*/
+typedef struct {
+ float sow; /* s texture ordinate (s over w) */
+ float tow; /* t texture ordinate (t over w) */
+ float oow; /* 1/w (used mipmapping - really 0xfff/w) */
+} GrTmuVertex;
+
+typedef struct
+{
+ float x, y; /* X and Y in screen space */
+ float ooz; /* 65535/Z (used for Z-buffering) */
+ float oow; /* 1/W (used for W-buffering, texturing) */
+ float r, g, b, a; /* R, G, B, A [0..255.0] */
+ float z; /* Z is ignored */
+ GrTmuVertex tmuvtx[GLIDE_NUM_TMU];
+} GrVertex;
+
+#define GR_VERTEX_X_OFFSET 0
+#define GR_VERTEX_Y_OFFSET 1
+#define GR_VERTEX_OOZ_OFFSET 2
+#define GR_VERTEX_OOW_OFFSET 3
+#define GR_VERTEX_R_OFFSET 4
+#define GR_VERTEX_G_OFFSET 5
+#define GR_VERTEX_B_OFFSET 6
+#define GR_VERTEX_A_OFFSET 7
+#define GR_VERTEX_Z_OFFSET 8
+#define GR_VERTEX_SOW_TMU0_OFFSET 9
+#define GR_VERTEX_TOW_TMU0_OFFSET 10
+#define GR_VERTEX_OOW_TMU0_OFFSET 11
+#define GR_VERTEX_SOW_TMU1_OFFSET 12
+#define GR_VERTEX_TOW_TMU1_OFFSET 13
+#define GR_VERTEX_OOW_TMU1_OFFSET 14
+
+#endif
+
+
+/*
+ * Glide2 functions for Glide3
+ */
+#if defined(FX_GLIDE3)
+#define FX_grTexDownloadTable(TMU,type,data) grTexDownloadTable(type,data)
+#else
+#define FX_grTexDownloadTable(TMU,type,data) grTexDownloadTable(TMU,type,data)
+#endif
+
+/*
+ * Flush
+ */
+#if defined(FX_GLIDE3)
+#define FX_grFlush grFlush
+#else
+#define FX_grFlush grSstIdle
+#endif
+/*
+ * Write region: ToDo possible exploit the PixelPipe parameter.
+ */
+#if defined(FX_GLIDE3)
+#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
+ grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data)
+#else
+#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
+ grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
+#endif
+/*
+ * For Lod/LodLog2 conversion.
+ */
+#if defined(FX_GLIDE3)
+ #define FX_largeLodLog2(info) (info).largeLodLog2
+#else
+ #define FX_largeLodLog2(info) (info).largeLod
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_aspectRatioLog2(info) (info).aspectRatioLog2
+#else
+ #define FX_aspectRatioLog2(info) (info).aspectRatio
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_smallLodLog2(info) (info).smallLodLog2
+#else
+ #define FX_smallLodLog2(info) (info).smallLod
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_lodToValue(val) ((int)(GR_LOD_256-val))
+#else
+ #define FX_lodToValue(val) ((int)(val))
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_largeLodValue(info) ((int)(GR_LOD_256-(info).largeLodLog2))
+#else
+ #define FX_largeLodValue(info) ((int)(info).largeLod)
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_smallLodValue(info) ((int)(GR_LOD_256-(info).smallLodLog2))
+#else
+ #define FX_smallLodValue(info) ((int)(info).smallLod)
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_valueToLod(val) ((GrLOD_t)(GR_LOD_256-val))
+#else
+ #define FX_valueToLod(val) ((GrLOD_t)(val))
+#endif
+
+/*
+ * ScreenWidth/Height stuff.
+ */
+#if defined(FX_GLIDE3)
+ extern int FX_grSstScreenWidth();
+ extern int FX_grSstScreenHeight();
+#else
+ #define FX_grSstScreenWidth() grSstScreenWidth()
+ #define FX_grSstScreenHeight() grSstScreenHeight()
+#endif
+
+
+/*
+ * Version string.
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grGlideGetVersion(char *buf);
+#else
+ #define FX_grGlideGetVersion grGlideGetVersion
+#endif
+/*
+ * Performance statistics
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grSstPerfStats(GrSstPerfStats_t *st);
+#else
+ #define FX_grSstPerfStats grSstPerfStats
+#endif
+
+/*
+ * Hardware Query
+ */
+#if defined(FX_GLIDE3)
+ extern int FX_grSstQueryHardware(GrHwConfiguration *config);
+#else
+ #define FX_grSstQueryHardware grSstQueryHardware
+#endif
+
+/*
+ * GrHints
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grHints(GrHint_t hintType, FxU32 hintMask);
+#else
+ #define FX_grHints grHints
+#endif
+/*
+ * Antialiashed line+point drawing.
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grAADrawLine(GrVertex *a,GrVertex *b);
+#else
+ #define FX_grAADrawLine grAADrawLine
+#endif
+
+#if defined(FX_GLIDE3)
+ extern void FX_grAADrawPoint(GrVertex *a);
+#else
+ #define FX_grAADrawPoint grAADrawPoint
+#endif
+
+/*
+ * Needed for Glide3 only, to set up Glide2 compatible vertex layout.
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_setupGrVertexLayout(void);
+#else
+ #define FX_setupGrVertexLayout() do {} while (0)
+#endif
+/*
+ * grSstControl stuff
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grSstControl(int par);
+#else
+ #define FX_grSstControl grSstControl
+#endif
+/*
+ * grGammaCorrectionValue
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grGammaCorrectionValue(float val);
+#else
+ #define FX_grGammaCorrectionValue grGammaCorrectionValue
+#endif
+
+/*
+ * WinOpen/Close.
+ */
+#if defined(FX_GLIDE3)
+ #define FX_grSstWinOpen(hWnd,screen_resolution,refresh_rate,color_format,origin_location,nColBuffers,nAuxBuffers) \
+ grSstWinOpen(-1,screen_resolution,refresh_rate,color_format,origin_location,nColBuffers,nAuxBuffers)
+ #define FX_grSstWinClose grSstWinClose
+#else
+ #define FX_grSstWinOpen grSstWinOpen
+ #define FX_grSstWinClose(win) grSstWinClose()
+#endif
+
+
+#endif /* __FX_GLIDE_WARPER__ */
diff --git a/src/mesa/drivers/glide/fxopengl.def b/src/mesa/drivers/glide/fxopengl.def
new file mode 100644
index 0000000000..af76f4c1b2
--- /dev/null
+++ b/src/mesa/drivers/glide/fxopengl.def
@@ -0,0 +1,467 @@
+EXPORTS
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glArrayElement
+ glBegin
+ glBindTexture
+ glBitmap
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearIndex
+ glClearColor
+ glClearDepth
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3d
+ glColor3f
+ glColor3i
+ glColor3s
+ glColor3ub
+ glColor3ui
+ glColor3us
+ glColor4b
+ glColor4d
+ glColor4f
+ glColor4i
+ glColor4s
+ glColor4ub
+ glColor4ui
+ glColor4us
+ glColor3bv
+ glColor3dv
+ glColor3fv
+ glColor3iv
+ glColor3sv
+ glColor3ubv
+ glColor3uiv
+ glColor3usv
+ glColor4bv
+ glColor4dv
+ glColor4fv
+ glColor4iv
+ glColor4sv
+ glColor4ubv
+ glColor4uiv
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorTableEXT
+ glColorSubTableEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCullFace
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDeleteLists
+ glDeleteTextures
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1f
+ glEvalCoord1dv
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2f
+ glEvalCoord2dv
+ glEvalCoord2fv
+ glEvalPoint1
+ glEvalPoint2
+ glEvalMesh1
+ glEdgeFlag
+ glEdgeFlagv
+ glEdgeFlagPointer
+ glEvalMesh2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogi
+ glFogfv
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGetBooleanv
+ glGetClipPlane
+ glGetColorTableEXT
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterfvEXT
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGeniv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexd
+ glIndexf
+ glIndexi
+ glIndexs
+ glIndexub
+ glIndexdv
+ glIndexfv
+ glIndexiv
+ glIndexsv
+ glIndexubv
+ glIndexMask
+ glIndexPointer
+ glInterleavedArrays
+ glInitNames
+ glIsList
+ glIsTexture
+ glLightf
+ glLighti
+ glLightfv
+ glLightiv
+ glLightModelf
+ glLightModeli
+ glLightModelfv
+ glLightModeliv
+ glLineWidth
+ glLineStipple
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMateriali
+ glMaterialfv
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3d
+ glNormal3f
+ glNormal3i
+ glNormal3s
+ glNormal3bv
+ glNormal3dv
+ glNormal3fv
+ glNormal3iv
+ glNormal3sv
+ glNormalPointer
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPushMatrix
+ glRasterPos2d
+ glRasterPos2f
+ glRasterPos2i
+ glRasterPos2s
+ glRasterPos3d
+ glRasterPos3f
+ glRasterPos3i
+ glRasterPos3s
+ glRasterPos4d
+ glRasterPos4f
+ glRasterPos4i
+ glRasterPos4s
+ glRasterPos2dv
+ glRasterPos2fv
+ glRasterPos2iv
+ glRasterPos2sv
+ glRasterPos3dv
+ glRasterPos3fv
+ glRasterPos3iv
+ glRasterPos3sv
+ glRasterPos4dv
+ glRasterPos4fv
+ glRasterPos4iv
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectf
+ glRecti
+ glRects
+ glRectdv
+ glRectfv
+ glRectiv
+ glRectsv
+ glScissor
+ glIsEnabled
+ glPushAttrib
+ glPushClientAttrib
+ glPushName
+ glRenderMode
+ glRotated
+ glRotatef
+ glSelectBuffer
+ glScaled
+ glScalef
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1f
+ glTexCoord1i
+ glTexCoord1s
+ glTexCoord2d
+ glTexCoord2f
+ glTexCoord2i
+ glTexCoord2s
+ glTexCoord3d
+ glTexCoord3f
+ glTexCoord3i
+ glTexCoord3s
+ glTexCoord4d
+ glTexCoord4f
+ glTexCoord4i
+ glTexCoord4s
+ glTexCoord1dv
+ glTexCoord1fv
+ glTexCoord1iv
+ glTexCoord1sv
+ glTexCoord2dv
+ glTexCoord2fv
+ glTexCoord2iv
+ glTexCoord2sv
+ glTexCoord3dv
+ glTexCoord3fv
+ glTexCoord3iv
+ glTexCoord3sv
+ glTexCoord4dv
+ glTexCoord4fv
+ glTexCoord4iv
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexGend
+ glTexGenf
+ glTexGeni
+ glTexGendv
+ glTexGeniv
+ glTexGenfv
+ glTexEnvf
+ glTexEnvi
+ glTexEnvfv
+ glTexEnviv
+ glTexImage1D
+ glTexImage2D
+ glTexParameterf
+ glTexParameteri
+ glTexParameterfv
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2f
+ glVertex2i
+ glVertex2s
+ glVertex3d
+ glVertex3f
+ glVertex3i
+ glVertex3s
+ glVertex4d
+ glVertex4f
+ glVertex4i
+ glVertex4s
+ glVertex2dv
+ glVertex2fv
+ glVertex2iv
+ glVertex2sv
+ glVertex3dv
+ glVertex3fv
+ glVertex3iv
+ glVertex3sv
+ glVertex4dv
+ glVertex4fv
+ glVertex4iv
+ glVertex4sv
+ glVertexPointer
+ glViewport
+ glBlendEquationEXT
+ glBlendColorEXT
+ glVertexPointerEXT
+ glNormalPointerEXT
+ glColorPointerEXT
+ glIndexPointerEXT
+ glTexCoordPointerEXT
+ glEdgeFlagPointerEXT
+ glGetPointervEXT
+ glArrayElementEXT
+ glDrawArraysEXT
+ glBindTextureEXT
+ glDeleteTexturesEXT
+ glGenTexturesEXT
+ glPrioritizeTexturesEXT
+ glCopyTexSubImage3DEXT
+ glTexImage3DEXT
+ glTexSubImage3DEXT
+ glWindowPos4fMESA
+ glWindowPos2iMESA
+ glWindowPos2sMESA
+ glWindowPos2fMESA
+ glWindowPos2dMESA
+ glWindowPos2ivMESA
+ glWindowPos2svMESA
+ glWindowPos2fvMESA
+ glWindowPos2dvMESA
+ glWindowPos3iMESA
+ glWindowPos3sMESA
+ glWindowPos3fMESA
+ glWindowPos3dMESA
+ glWindowPos3ivMESA
+ glWindowPos3svMESA
+ glWindowPos3fvMESA
+ glWindowPos3dvMESA
+ glWindowPos4iMESA
+ glWindowPos4sMESA
+ glWindowPos4dMESA
+ glWindowPos4ivMESA
+ glWindowPos4svMESA
+ glWindowPos4fvMESA
+ glWindowPos4dvMESA
+ glResizeBuffersMESA
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+;wglDescribeLayerPlane
+ wglGetCurrentContext
+ wglGetCurrentDC
+;wglGetLayerPaletteEntries
+ wglGetProcAddress
+ wglMakeCurrent
+;wglRealizeLayerPalette
+;wglSetLayerPaletteEntries
+ wglShareLists
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ wglChoosePixelFormat
+ ChoosePixelFormat
+ wglDescribePixelFormat
+ DescribePixelFormat
+ wglGetPixelFormat
+ GetPixelFormat
+ wglSetPixelFormat
+ SetPixelFormat
+ wglSwapBuffers
+ SwapBuffers
+ gl3DfxSetPaletteEXT
+ glActiveTextureARB
+ glClientActiveTextureARB
+ glMultiTexCoord1dARB
+ glMultiTexCoord1dvARB
+ glMultiTexCoord1fARB
+ glMultiTexCoord1fvARB
+ glMultiTexCoord1iARB
+ glMultiTexCoord1ivARB
+ glMultiTexCoord1sARB
+ glMultiTexCoord1svARB
+ glMultiTexCoord2dARB
+ glMultiTexCoord2dvARB
+ glMultiTexCoord2fARB
+ glMultiTexCoord2fvARB
+ glMultiTexCoord2iARB
+ glMultiTexCoord2ivARB
+ glMultiTexCoord2sARB
+ glMultiTexCoord2svARB
+ glMultiTexCoord3dARB
+ glMultiTexCoord3dvARB
+ glMultiTexCoord3fARB
+ glMultiTexCoord3fvARB
+ glMultiTexCoord3iARB
+ glMultiTexCoord3ivARB
+ glMultiTexCoord3sARB
+ glMultiTexCoord3svARB
+ glMultiTexCoord4dARB
+ glMultiTexCoord4dvARB
+ glMultiTexCoord4fARB
+ glMultiTexCoord4fvARB
+ glMultiTexCoord4iARB
+ glMultiTexCoord4ivARB
+ glMultiTexCoord4sARB
+ glMultiTexCoord4svARB
+ fxMesaCreateContext
+ fxMesaCreateBestContext
+ fxMesaDestroyContext
+ fxMesaSelectCurrentBoard
+ fxMesaMakeCurrent
+ fxMesaGetCurrentContext
+ fxMesaSwapBuffers
+ fxMesaSetNearFar
+ fxMesaUpdateScreenSize
+ fxQueryHardware
+ fxCloseHardware
+ OSMesaCreateContext
+ OSMesaDestroyContext
+ OSMesaGetCurrentContext
+ OSMesaGetDepthBuffer
+ OSMesaGetIntegerv
+ OSMesaMakeCurrent
+ OSMesaPixelStore
diff --git a/src/mesa/drivers/glide/fxsetup.c b/src/mesa/drivers/glide/fxsetup.c
new file mode 100644
index 0000000000..9996499316
--- /dev/null
+++ b/src/mesa/drivers/glide/fxsetup.c
@@ -0,0 +1,1552 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxsetup.c - 3Dfx VooDoo rendering mode setup functions
+*/
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "enums.h"
+
+static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ GLint minl,maxl;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTexValidate(...) Start\n");
+ }
+
+ if(ti->validated) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTexValidate(...) End (validated=GL_TRUE)\n");
+ }
+ return;
+ }
+
+ minl=ti->minLevel=tObj->BaseLevel;
+ maxl=ti->maxLevel=MIN2(tObj->MaxLevel,tObj->Image[0]->MaxLog2);
+
+ fxTexGetInfo(tObj->Image[minl]->Width,tObj->Image[minl]->Height,
+ &(FX_largeLodLog2(ti->info)),&(FX_aspectRatioLog2(ti->info)),
+ &(ti->sScale),&(ti->tScale),
+ &(ti->int_sScale),&(ti->int_tScale),
+ NULL,NULL);
+
+
+ if((tObj->MinFilter!=GL_NEAREST) && (tObj->MinFilter!=GL_LINEAR))
+ fxTexGetInfo(tObj->Image[maxl]->Width,tObj->Image[maxl]->Height,
+ &(FX_smallLodLog2(ti->info)),NULL,
+ NULL,NULL,
+ NULL,NULL,
+ NULL,NULL);
+ else
+ FX_smallLodLog2(ti->info)=FX_largeLodLog2(ti->info);
+
+ fxTexGetFormat(tObj->Image[minl]->Format,&(ti->info.format),&(ti->baseLevelInternalFormat));
+
+ ti->validated=GL_TRUE;
+
+ ti->info.data=NULL;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTexValidate(...) End\n");
+ }
+}
+
+static void fxPrintUnitsMode( const char *msg, GLuint mode )
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ mode,
+ (mode & FX_UM_E0_REPLACE) ? "E0_REPLACE, " : "",
+ (mode & FX_UM_E0_MODULATE) ? "E0_MODULATE, " : "",
+ (mode & FX_UM_E0_DECAL) ? "E0_DECAL, " : "",
+ (mode & FX_UM_E0_BLEND) ? "E0_BLEND, " : "",
+ (mode & FX_UM_E1_REPLACE) ? "E1_REPLACE, " : "",
+ (mode & FX_UM_E1_MODULATE) ? "E1_MODULATE, " : "",
+ (mode & FX_UM_E1_DECAL) ? "E1_DECAL, " : "",
+ (mode & FX_UM_E1_BLEND) ? "E1_BLEND, " : "",
+ (mode & FX_UM_E0_ALPHA) ? "E0_ALPHA, " : "",
+ (mode & FX_UM_E0_LUMINANCE) ? "E0_LUMINANCE, " : "",
+ (mode & FX_UM_E0_LUMINANCE_ALPHA) ? "E0_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E0_INTENSITY) ? "E0_INTENSITY, " : "",
+ (mode & FX_UM_E0_RGB) ? "E0_RGB, " : "",
+ (mode & FX_UM_E0_RGBA) ? "E0_RGBA, " : "",
+ (mode & FX_UM_E1_ALPHA) ? "E1_ALPHA, " : "",
+ (mode & FX_UM_E1_LUMINANCE) ? "E1_LUMINANCE, " : "",
+ (mode & FX_UM_E1_LUMINANCE_ALPHA) ? "E1_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E1_INTENSITY) ? "E1_INTENSITY, " : "",
+ (mode & FX_UM_E1_RGB) ? "E1_RGB, " : "",
+ (mode & FX_UM_E1_RGBA) ? "E1_RGBA, " : "",
+ (mode & FX_UM_COLOR_ITERATED) ? "COLOR_ITERATED, " : "",
+ (mode & FX_UM_COLOR_CONSTANT) ? "COLOR_CONSTANT, " : "",
+ (mode & FX_UM_ALPHA_ITERATED) ? "ALPHA_ITERATED, " : "",
+ (mode & FX_UM_ALPHA_CONSTANT) ? "ALPHA_CONSTANT, " : "");
+}
+
+GLuint fxGetTexSetConfiguration(GLcontext *ctx,
+ struct gl_texture_object *tObj0,
+ struct gl_texture_object *tObj1)
+{
+ GLuint unitsmode=0;
+ GLuint envmode=0;
+ GLuint ifmt=0;
+
+ if((ctx->Light.ShadeModel==GL_SMOOTH) ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag))
+ unitsmode|=FX_UM_ALPHA_ITERATED;
+ else
+ unitsmode|=FX_UM_ALPHA_CONSTANT;
+
+ if(ctx->Light.ShadeModel==GL_SMOOTH)
+ unitsmode|=FX_UM_COLOR_ITERATED;
+ else
+ unitsmode|=FX_UM_COLOR_CONSTANT;
+
+ if(tObj0) {
+ tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData;
+
+ switch(ti0->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt|=FX_UM_E0_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt|=FX_UM_E0_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt|=FX_UM_E0_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt|=FX_UM_E0_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt|=FX_UM_E0_RGB;
+ break;
+ case GL_RGBA:
+ ifmt|=FX_UM_E0_RGBA;
+ break;
+ }
+
+ switch(ctx->Texture.Unit[0].EnvMode) {
+ case GL_DECAL:
+ envmode|=FX_UM_E0_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode|=FX_UM_E0_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode|=FX_UM_E0_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode|=FX_UM_E0_BLEND;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ if(tObj1) {
+ tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData;
+
+ switch(ti1->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt|=FX_UM_E1_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt|=FX_UM_E1_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt|=FX_UM_E1_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt|=FX_UM_E1_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt|=FX_UM_E1_RGB;
+ break;
+ case GL_RGBA:
+ ifmt|=FX_UM_E1_RGBA;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ switch(ctx->Texture.Unit[1].EnvMode) {
+ case GL_DECAL:
+ envmode|=FX_UM_E1_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode|=FX_UM_E1_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode|=FX_UM_E1_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode|=FX_UM_E1_BLEND;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ unitsmode|=(ifmt | envmode);
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fxPrintUnitsMode("unitsmode", unitsmode);
+
+ return unitsmode;
+}
+
+/************************************************************************/
+/************************* Rendering Mode SetUp *************************/
+/************************************************************************/
+
+/************************* Single Texture Set ***************************/
+
+static void fxSetupSingleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+
+ if(!ti->tmi.isInTM) {
+ if(ti->LODblend)
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU_SPLIT);
+ else {
+ if(fxMesa->haveTwoTMUs) {
+ if(fxMesa->freeTexMem[FX_TMU0]>grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info)))
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU0);
+ else
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU1);
+ } else
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU0);
+ }
+ }
+
+ if(ti->LODblend && ti->tmi.whichTMU == FX_TMU_SPLIT) {
+ if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette\n");
+ }
+ FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette));
+ FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(ti->palette));
+ }
+
+ grTexClampMode(GR_TMU0,ti->sClamp,ti->tClamp);
+ grTexClampMode(GR_TMU1,ti->sClamp,ti->tClamp);
+ grTexFilterMode(GR_TMU0,ti->minFilt,ti->maxFilt);
+ grTexFilterMode(GR_TMU1,ti->minFilt,ti->maxFilt);
+ grTexMipMapMode(GR_TMU0,ti->mmMode,ti->LODblend);
+ grTexMipMapMode(GR_TMU1,ti->mmMode,ti->LODblend);
+
+ grTexSource(GR_TMU0,ti->tmi.tm[FX_TMU0]->startAddress,
+ GR_MIPMAPLEVELMASK_ODD,&(ti->info));
+ grTexSource(GR_TMU1,ti->tmi.tm[FX_TMU1]->startAddress,
+ GR_MIPMAPLEVELMASK_EVEN,&(ti->info));
+ } else {
+ if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette\n");
+ }
+ FX_grTexDownloadTable(ti->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti->palette));
+ }
+
+ /* KW: The alternative is to do the download to the other tmu. If
+ * we get to this point, I think it means we are thrashing the
+ * texture memory, so perhaps it's not a good idea.
+ */
+ if (ti->LODblend && (MESA_VERBOSE&VERBOSE_DRIVER))
+ fprintf(stderr, "fxmesa: not blending texture - only on one tmu\n");
+
+ grTexClampMode(ti->tmi.whichTMU,ti->sClamp,ti->tClamp);
+ grTexFilterMode(ti->tmi.whichTMU,ti->minFilt,ti->maxFilt);
+ grTexMipMapMode(ti->tmi.whichTMU,ti->mmMode,FXFALSE);
+
+ grTexSource(ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]->startAddress,
+ GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
+ }
+}
+
+static void fxSelectSingleTMUSrc(fxMesaContext fxMesa, GLint tmu, FxBool LODblend)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSelectSingleTMUSrc(%d,%d)\n",tmu,LODblend);
+ }
+
+ if(LODblend) {
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION,
+ GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION,
+ FXFALSE,FXFALSE);
+
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ fxMesa->tmuSrc=FX_TMU_SPLIT;
+ } else {
+ if(tmu==FX_TMU0) {
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ fxMesa->tmuSrc=FX_TMU0;
+ } else {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE,
+ GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE,
+ FXFALSE,FXFALSE);
+
+ fxMesa->tmuSrc=FX_TMU1;
+ }
+ }
+}
+
+void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GrCombineLocal_t localc,locala;
+ GLuint unitsmode;
+ GLint ifmt;
+ tfxTexInfo *ti;
+ struct gl_texture_object *tObj=ctx->Texture.Unit[textureset].CurrentD[2];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) Start\n");
+ }
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ fxTexValidate(ctx,tObj);
+
+ fxSetupSingleTMU(fxMesa,tObj);
+
+ if(fxMesa->tmuSrc!=ti->tmi.whichTMU)
+ fxSelectSingleTMUSrc(fxMesa,ti->tmi.whichTMU,ti->LODblend);
+
+ if(textureset==0 || !fxMesa->haveTwoTMUs)
+ unitsmode=fxGetTexSetConfiguration(ctx,tObj,NULL);
+ else
+ unitsmode=fxGetTexSetConfiguration(ctx,NULL,tObj);
+
+ if(fxMesa->lastUnitsMode==unitsmode)
+ return;
+
+ fxMesa->lastUnitsMode=unitsmode;
+
+ fxMesa->stw_hint_state = 0;
+ FX_grHints(GR_HINT_STWHINT,0);
+
+ ifmt=ti->baseLevelInternalFormat;
+
+ if(unitsmode & FX_UM_ALPHA_ITERATED)
+ locala=GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala=GR_COMBINE_LOCAL_CONSTANT;
+
+ if(unitsmode & FX_UM_COLOR_ITERATED)
+ localc=GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc=GR_COMBINE_LOCAL_CONSTANT;
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxMesa: fxSetupTextureSingleTMU, envmode is %s\n",
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode));
+
+ switch(ctx->Texture.Unit[textureset].EnvMode) {
+ case GL_DECAL:
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ case GL_MODULATE:
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ locala,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+
+ if(ifmt==GL_ALPHA)
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ case GL_BLEND:
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: GL_BLEND not yet supported\n");
+#endif
+ /* TO DO (I think that the Voodoo Graphics isn't able to support GL_BLEND) */
+ break;
+ case GL_REPLACE:
+ if((ifmt==GL_RGB) || (ifmt==GL_LUMINANCE))
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ locala,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+
+ if(ifmt==GL_ALPHA)
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ default:
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: %x Texture.EnvMode not yet supported\n",ctx->Texture.Unit[textureset].EnvMode);
+#endif
+ break;
+ }
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) End\n");
+ }
+}
+
+/************************* Double Texture Set ***************************/
+
+void fxSetupDoubleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj0,
+ struct gl_texture_object *tObj1)
+{
+#define T0_NOT_IN_TMU 0x01
+#define T1_NOT_IN_TMU 0x02
+#define T0_IN_TMU0 0x04
+#define T1_IN_TMU0 0x08
+#define T0_IN_TMU1 0x10
+#define T1_IN_TMU1 0x20
+
+ tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData;
+ tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData;
+ GLuint tstate=0;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupDoubleTMU(...)\n");
+ }
+
+ if(ti0->tmi.isInTM) {
+ if(ti0->tmi.whichTMU==FX_TMU0)
+ tstate|=T0_IN_TMU0;
+ else if(ti0->tmi.whichTMU==FX_TMU1)
+ tstate|=T0_IN_TMU1;
+ else {
+ fxTMMoveOutTM(fxMesa,tObj0);
+ tstate|=T0_NOT_IN_TMU;
+ }
+ } else
+ tstate|=T0_NOT_IN_TMU;
+
+ if(ti1->tmi.isInTM) {
+ if(ti1->tmi.whichTMU==FX_TMU0)
+ tstate|=T1_IN_TMU0;
+ else if(ti1->tmi.whichTMU==FX_TMU1)
+ tstate|=T1_IN_TMU1;
+ else {
+ fxTMMoveOutTM(fxMesa,tObj1);
+ tstate|=T1_NOT_IN_TMU;
+ }
+ } else
+ tstate|=T1_NOT_IN_TMU;
+
+ ti0->tmi.lastTimeUsed=fxMesa->texBindNumber;
+ ti1->tmi.lastTimeUsed=fxMesa->texBindNumber;
+
+ /* Move texture maps in TMUs */
+
+ switch(tstate) {
+ case (T0_IN_TMU0 | T1_IN_TMU0):
+ fxTMMoveOutTM(fxMesa,tObj1);
+
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU1);
+ break;
+
+ case (T0_IN_TMU1 | T1_IN_TMU1):
+ fxTMMoveOutTM(fxMesa,tObj0);
+
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU0);
+ break;
+
+ case (T0_NOT_IN_TMU | T1_NOT_IN_TMU):
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU0);
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU1);
+ break;
+
+ /*** T0/T1 ***/
+
+ case (T0_NOT_IN_TMU | T1_IN_TMU0):
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU1);
+ break;
+
+ case (T0_NOT_IN_TMU | T1_IN_TMU1):
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU0);
+ break;
+
+ case (T0_IN_TMU0 | T1_NOT_IN_TMU):
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU1);
+ break;
+
+ case (T0_IN_TMU1 | T1_NOT_IN_TMU):
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU0);
+ break;
+
+ /*** Best Case ***/
+
+ case (T0_IN_TMU1 | T1_IN_TMU0):
+ case (T0_IN_TMU0 | T1_IN_TMU1):
+ break;
+
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxSetupDoubleTMU()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+
+ if(!fxMesa->haveGlobalPaletteTexture) {
+ if(ti0->info.format==GR_TEXFMT_P_8) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette TMU0\n");
+ }
+ FX_grTexDownloadTable(ti0->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti0->palette));
+ }
+
+ if(ti1->info.format==GR_TEXFMT_P_8) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette TMU1\n");
+ }
+ FX_grTexDownloadTable(ti1->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti1->palette));
+ }
+ }
+
+ grTexClampMode(ti0->tmi.whichTMU,ti0->sClamp,ti0->tClamp);
+ grTexFilterMode(ti0->tmi.whichTMU,ti0->minFilt,ti0->maxFilt);
+ grTexMipMapMode(ti0->tmi.whichTMU,ti0->mmMode,FXFALSE);
+ grTexSource(ti0->tmi.whichTMU,ti0->tmi.tm[ti0->tmi.whichTMU]->startAddress,
+ GR_MIPMAPLEVELMASK_BOTH,&(ti0->info));
+
+ grTexClampMode(ti1->tmi.whichTMU,ti1->sClamp,ti1->tClamp);
+ grTexFilterMode(ti1->tmi.whichTMU,ti1->minFilt,ti1->maxFilt);
+ grTexMipMapMode(ti1->tmi.whichTMU,ti1->mmMode,FXFALSE);
+ grTexSource(ti1->tmi.whichTMU,ti1->tmi.tm[ti1->tmi.whichTMU]->startAddress,
+ GR_MIPMAPLEVELMASK_BOTH,&(ti1->info));
+
+#undef T0_NOT_IN_TMU
+#undef T1_NOT_IN_TMU
+#undef T0_IN_TMU0
+#undef T1_IN_TMU0
+#undef T0_IN_TMU1
+#undef T1_IN_TMU1
+}
+
+static void fxSetupTextureDoubleTMU(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GrCombineLocal_t localc,locala;
+ tfxTexInfo *ti0,*ti1;
+ struct gl_texture_object *tObj0=ctx->Texture.Unit[0].CurrentD[2];
+ struct gl_texture_object *tObj1=ctx->Texture.Unit[1].CurrentD[2];
+ GLuint envmode,ifmt,unitsmode;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) Start\n");
+ }
+
+ ti0=(tfxTexInfo *)tObj0->DriverData;
+ fxTexValidate(ctx,tObj0);
+
+ ti1=(tfxTexInfo *)tObj1->DriverData;
+ fxTexValidate(ctx,tObj1);
+
+ fxSetupDoubleTMU(fxMesa,tObj0,tObj1);
+
+ unitsmode=fxGetTexSetConfiguration(ctx,tObj0,tObj1);
+
+ if(fxMesa->lastUnitsMode==unitsmode)
+ return;
+
+ fxMesa->lastUnitsMode=unitsmode;
+
+ fxMesa->stw_hint_state |= GR_STWHINT_ST_DIFF_TMU1;
+ FX_grHints(GR_HINT_STWHINT, fxMesa->stw_hint_state);
+
+ envmode=unitsmode & FX_UM_E_ENVMODE;
+ ifmt=unitsmode & FX_UM_E_IFMT;
+
+ if(unitsmode & FX_UM_ALPHA_ITERATED)
+ locala=GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala=GR_COMBINE_LOCAL_CONSTANT;
+
+ if(unitsmode & FX_UM_COLOR_ITERATED)
+ localc=GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc=GR_COMBINE_LOCAL_CONSTANT;
+
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxMesa: fxSetupTextureDoubleTMU, envmode is %s/%s\n",
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+
+ fxMesa->tmuSrc=FX_TMU_BOTH;
+ switch(envmode) {
+ case (FX_UM_E0_MODULATE | FX_UM_E1_MODULATE):
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ if(ti0->baseLevelInternalFormat==GL_ALPHA)
+ isalpha[ti0->tmi.whichTMU]=GL_TRUE;
+ else
+ isalpha[ti0->tmi.whichTMU]=GL_FALSE;
+
+ if(ti1->baseLevelInternalFormat==GL_ALPHA)
+ isalpha[ti1->tmi.whichTMU]=GL_TRUE;
+ else
+ isalpha[ti1->tmi.whichTMU]=GL_FALSE;
+
+ if(isalpha[FX_TMU1])
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXTRUE,FXFALSE);
+ else
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ if(isalpha[FX_TMU0])
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+ else
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ locala,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ }
+ case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */
+ if(ti1->tmi.whichTMU==FX_TMU1) {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXTRUE,FXFALSE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+ } else {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
+ FXFALSE,FXFALSE);
+ }
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */
+ if(ti1->tmi.whichTMU==FX_TMU1) {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXTRUE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+
+ } else {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE,
+ FXFALSE,FXFALSE);
+ }
+
+ if(ti0->baseLevelInternalFormat==GL_RGB)
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ }
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) End\n");
+ }
+}
+
+/************************* No Texture ***************************/
+
+static void fxSetupTextureNone(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GrCombineLocal_t localc,locala;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureNone(...)\n");
+ }
+
+ if((ctx->Light.ShadeModel==GL_SMOOTH) ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag))
+ locala=GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala=GR_COMBINE_LOCAL_CONSTANT;
+
+ if(ctx->Light.ShadeModel==GL_SMOOTH)
+ localc=GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc=GR_COMBINE_LOCAL_CONSTANT;
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ fxMesa->lastUnitsMode=FX_UM_NONE;
+}
+
+/* See below.
+ */
+static GLboolean fxMultipassTexture( struct vertex_buffer *, GLuint );
+
+
+
+/************************************************************************/
+/************************** Texture Mode SetUp **************************/
+/************************************************************************/
+
+void fxSetupTexture(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint tex2Denabled;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTexture(...)\n");
+ }
+
+ /* Disable multipass texturing.
+ */
+ ctx->Driver.MultipassFunc = 0;
+
+ /* Texture Combine, Color Combine and Alpha Combine.
+ */
+ tex2Denabled = (ctx->Texture.ReallyEnabled & TEXTURE0_2D);
+
+ if (fxMesa->emulateTwoTMUs)
+ tex2Denabled |= (ctx->Texture.ReallyEnabled & TEXTURE1_2D);
+
+ switch(tex2Denabled) {
+ case TEXTURE0_2D:
+ fxSetupTextureSingleTMU(ctx,0);
+ break;
+ case TEXTURE1_2D:
+ fxSetupTextureSingleTMU(ctx,1);
+ break;
+ case (TEXTURE0_2D|TEXTURE1_2D):
+ if (fxMesa->haveTwoTMUs)
+ fxSetupTextureDoubleTMU(ctx);
+ else {
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ fprintf(stderr, "fxmesa: enabling fake multitexture\n");
+
+ fxSetupTextureSingleTMU(ctx,0);
+ ctx->Driver.MultipassFunc = fxMultipassTexture;
+ }
+ break;
+ default:
+ fxSetupTextureNone(ctx);
+ break;
+ }
+}
+
+/************************************************************************/
+/**************************** Blend SetUp *******************************/
+/************************************************************************/
+
+/* XXX consider supporting GL_INGR_blend_func_separate */
+void fxDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+ GrAlphaBlendFnc_t sfact,dfact,asfact,adfact;
+
+ /* From the Glide documentation:
+ For alpha source and destination blend function factor
+ parameters, Voodoo Graphics supports only
+ GR_BLEND_ZERO and GR_BLEND_ONE.
+ */
+
+ switch(sfactor) {
+ case GL_ZERO:
+ asfact=sfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ asfact=sfact=GR_BLEND_ONE;
+ break;
+ case GL_DST_COLOR:
+ sfact=GR_BLEND_DST_COLOR;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sfact=GR_BLEND_ONE_MINUS_DST_COLOR;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_ALPHA:
+ sfact=GR_BLEND_SRC_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_DST_ALPHA:
+ sfact=GR_BLEND_DST_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sfact=GR_BLEND_ONE_MINUS_DST_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ sfact=GR_BLEND_ALPHA_SATURATE;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ /* USELESS */
+ asfact=sfact=GR_BLEND_ONE;
+ break;
+ default:
+ asfact=sfact=GR_BLEND_ONE;
+ break;
+ }
+
+ if((sfact!=us->blendSrcFuncRGB) ||
+ (asfact!=us->blendSrcFuncAlpha)) {
+ us->blendSrcFuncRGB=sfact;
+ us->blendSrcFuncAlpha=asfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+
+ switch(dfactor) {
+ case GL_ZERO:
+ adfact=dfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ adfact=dfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ dfact=GR_BLEND_SRC_COLOR;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dfact=GR_BLEND_ONE_MINUS_SRC_COLOR;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_SRC_ALPHA:
+ dfact=GR_BLEND_SRC_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_DST_ALPHA:
+ dfact=GR_BLEND_DST_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dfact=GR_BLEND_ONE_MINUS_DST_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ /* USELESS */
+ adfact=dfact=GR_BLEND_ZERO;
+ break;
+ default:
+ adfact=dfact=GR_BLEND_ZERO;
+ break;
+ }
+
+ if((dfact!=us->blendDstFuncRGB) ||
+ (adfact!=us->blendDstFuncAlpha)) {
+ us->blendDstFuncRGB=dfact;
+ us->blendDstFuncAlpha=adfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+void fxSetupBlend(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(us->blendEnabled)
+ grAlphaBlendFunction(us->blendSrcFuncRGB,us->blendDstFuncRGB,
+ us->blendSrcFuncAlpha,us->blendDstFuncAlpha);
+ else
+ grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO);
+}
+
+/************************************************************************/
+/************************** Alpha Test SetUp ****************************/
+/************************************************************************/
+
+void fxDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+ GrCmpFnc_t newfunc;
+
+ switch(func) {
+ case GL_NEVER:
+ newfunc=GR_CMP_NEVER;
+ break;
+ case GL_LESS:
+ newfunc=GR_CMP_LESS;
+ break;
+ case GL_EQUAL:
+ newfunc=GR_CMP_EQUAL;
+ break;
+ case GL_LEQUAL:
+ newfunc=GR_CMP_LEQUAL;
+ break;
+ case GL_GREATER:
+ newfunc=GR_CMP_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ newfunc=GR_CMP_NOTEQUAL;
+ break;
+ case GL_GEQUAL:
+ newfunc=GR_CMP_GEQUAL;
+ break;
+ case GL_ALWAYS:
+ newfunc=GR_CMP_ALWAYS;
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxDDAlphaFunc()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+
+ if(newfunc!=us->alphaTestFunc) {
+ us->alphaTestFunc=newfunc;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+
+ if(ctx->Color.AlphaRef!=us->alphaTestRefValue) {
+ us->alphaTestRefValue=ctx->Color.AlphaRef;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+static void fxSetupAlphaTest(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(us->alphaTestEnabled) {
+ grAlphaTestFunction(us->alphaTestFunc);
+ grAlphaTestReferenceValue(us->alphaTestRefValue);
+ } else
+ grAlphaTestFunction(GR_CMP_ALWAYS);
+}
+
+/************************************************************************/
+/************************** Depth Test SetUp ****************************/
+/************************************************************************/
+
+void fxDDDepthFunc(GLcontext *ctx, GLenum func)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+ GrCmpFnc_t dfunc;
+
+ switch(func) {
+ case GL_NEVER:
+ dfunc=GR_CMP_NEVER;
+ break;
+ case GL_LESS:
+ dfunc=GR_CMP_LESS;
+ break;
+ case GL_GEQUAL:
+ dfunc=GR_CMP_GEQUAL;
+ break;
+ case GL_LEQUAL:
+ dfunc=GR_CMP_LEQUAL;
+ break;
+ case GL_GREATER:
+ dfunc=GR_CMP_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ dfunc=GR_CMP_NOTEQUAL;
+ break;
+ case GL_EQUAL:
+ dfunc=GR_CMP_EQUAL;
+ break;
+ case GL_ALWAYS:
+ dfunc=GR_CMP_ALWAYS;
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxDDDepthFunc()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+
+ if(dfunc!=us->depthTestFunc) {
+ us->depthTestFunc=dfunc;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+
+}
+
+void fxDDDepthMask(GLcontext *ctx, GLboolean flag)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(flag!=us->depthMask) {
+ us->depthMask=flag;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+void fxSetupDepthTest(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(us->depthTestEnabled)
+ grDepthBufferFunction(us->depthTestFunc);
+ else
+ grDepthBufferFunction(GR_CMP_ALWAYS);
+
+ grDepthMask(us->depthMask);
+}
+
+/************************************************************************/
+/**************************** Color Mask SetUp **************************/
+/************************************************************************/
+
+GLboolean fxDDColorMask(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ fxMesa->new_state |= FX_NEW_COLOR_MASK;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ (void) r; (void) g; (void) b; (void) a;
+ return 1;
+}
+
+static void fxSetupColorMask(GLcontext *ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ grColorMask(ctx->Color.ColorMask[RCOMP] ||
+ ctx->Color.ColorMask[GCOMP] ||
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer);
+}
+
+
+
+/************************************************************************/
+/**************************** Fog Mode SetUp ****************************/
+/************************************************************************/
+
+void fxFogTableGenerate(GLcontext *ctx)
+{
+ int i;
+ float f,eyez;
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ for(i=0;i<FX_grGetInteger(FX_FOG_TABLE_ENTRIES);i++) {
+ eyez=guFogTableIndexToW(i);
+
+ switch(ctx->Fog.Mode) {
+ case GL_LINEAR:
+ f=(ctx->Fog.End-eyez)/(ctx->Fog.End-ctx->Fog.Start);
+ break;
+ case GL_EXP:
+ f=exp(-ctx->Fog.Density*eyez);
+ break;
+ case GL_EXP2:
+ f=exp(-ctx->Fog.Density*ctx->Fog.Density*eyez*eyez);
+ break;
+ default: /* That should never happen */
+ f=0.0f;
+ break;
+ }
+
+ fxMesa->fogTable[i]=(GrFog_t)((1.0f-CLAMP(f,0.0f,1.0f))*255.0f);
+ }
+}
+
+void fxSetupFog(GLcontext *ctx, GLboolean forceTableRebuild)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if(ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) {
+ GLubyte col[4];
+ grFogMode(GR_FOG_WITH_TABLE);
+
+ col[0]=(unsigned int)(255*ctx->Fog.Color[0]);
+ col[1]=(unsigned int)(255*ctx->Fog.Color[1]);
+ col[2]=(unsigned int)(255*ctx->Fog.Color[2]);
+ col[3]=(unsigned int)(255*ctx->Fog.Color[3]);
+
+ grFogColorValue(FXCOLOR4(col));
+
+ if(forceTableRebuild ||
+ (fxMesa->fogTableMode!=ctx->Fog.Mode) ||
+ (fxMesa->fogDensity!=ctx->Fog.Density)) {
+ fxFogTableGenerate(ctx);
+
+ fxMesa->fogTableMode=ctx->Fog.Mode;
+ fxMesa->fogDensity=ctx->Fog.Density;
+ }
+
+ grFogTable(fxMesa->fogTable);
+ } else
+ grFogMode(GR_FOG_DISABLE);
+}
+
+void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+/************************************************************************/
+/************************** Scissor Test SetUp **************************/
+/************************************************************************/
+
+static void fxSetupScissor(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (ctx->Scissor.Enabled) {
+ int ymin, ymax;
+
+ ymin=ctx->Scissor.Y;
+ ymax=ctx->Scissor.Y+ctx->Scissor.Height;
+
+ if (ymin<0) ymin=0;
+
+ if (ymax>fxMesa->height) ymax=fxMesa->height;
+
+ grClipWindow(ctx->Scissor.X,
+ ymin,
+ ctx->Scissor.X+ctx->Scissor.Width,
+ ymax);
+ } else
+ grClipWindow(0,0,fxMesa->width,fxMesa->height);
+}
+
+void fxDDScissor( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_SCISSOR;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+/************************************************************************/
+/*************************** Cull mode setup ****************************/
+/************************************************************************/
+
+
+void fxDDCullFace(GLcontext *ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void fxDDFrontFace(GLcontext *ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+
+void fxSetupCull(GLcontext *ctx)
+{
+ if(ctx->Polygon.CullFlag) {
+ switch(ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if(ctx->Polygon.FrontFace==GL_CCW)
+ grCullMode(GR_CULL_NEGATIVE);
+ else
+ grCullMode(GR_CULL_POSITIVE);
+ break;
+ case GL_FRONT:
+ if(ctx->Polygon.FrontFace==GL_CCW)
+ grCullMode(GR_CULL_POSITIVE);
+ else
+ grCullMode(GR_CULL_NEGATIVE);
+ break;
+ case GL_FRONT_AND_BACK:
+ grCullMode(GR_CULL_DISABLE);
+ break;
+ default:
+ break;
+ }
+ } else
+ grCullMode(GR_CULL_DISABLE);
+}
+
+
+/************************************************************************/
+/****************************** DD Enable ******************************/
+/************************************************************************/
+
+void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDEnable(...)\n");
+ }
+
+ switch(cap) {
+ case GL_ALPHA_TEST:
+ if(state!=us->alphaTestEnabled) {
+ us->alphaTestEnabled=state;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+ break;
+ case GL_BLEND:
+ if(state!=us->blendEnabled) {
+ us->blendEnabled=state;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+ break;
+ case GL_DEPTH_TEST:
+ if(state!=us->depthTestEnabled) {
+ us->depthTestEnabled=state;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+ break;
+ case GL_SCISSOR_TEST:
+ fxMesa->new_state |= FX_NEW_SCISSOR;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ case GL_FOG:
+ fxMesa->new_state |= FX_NEW_FOG;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ case GL_CULL_FACE:
+ fxMesa->new_state |= FX_NEW_CULL;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ case GL_LINE_SMOOTH:
+ case GL_POINT_SMOOTH:
+ case GL_POLYGON_SMOOTH:
+ case GL_TEXTURE_2D:
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ default:
+ ; /* XXX no-op??? */
+ }
+}
+
+/************************************************************************/
+/******************** Fake Multitexture Support *************************/
+/************************************************************************/
+
+/* Its considered cheeky to try to fake ARB multitexture by doing
+ * multipass rendering, because it is not possible to emulate the full
+ * spec in this way. The fact is that the voodoo 2 supports only a
+ * subset of the possible multitexturing modes, and it is possible to
+ * support almost the same subset using multipass blending on the
+ * voodoo 1. In all other cases for both voodoo 1 and 2, we fall back
+ * to software rendering, satisfying the spec if not the user.
+ */
+static GLboolean fxMultipassTexture( struct vertex_buffer *VB, GLuint pass )
+{
+ GLcontext *ctx = VB->ctx;
+ fxVertex *v = FX_DRIVER_DATA(VB)->verts;
+ fxVertex *last = FX_DRIVER_DATA(VB)->last_vert;
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ switch (pass) {
+ case 1:
+ if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_PIPELINE|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxmesa: Second texture pass\n");
+
+ for ( ; v != last ; v++) {
+ v->f[S0COORD] = v->f[S1COORD];
+ v->f[T0COORD] = v->f[T1COORD];
+ }
+
+ fxMesa->restoreUnitsState = fxMesa->unitsState;
+ fxMesa->tmu_source[0] = 1;
+
+ if (ctx->Depth.Mask) {
+ switch (ctx->Depth.Func) {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ break;
+ default:
+ fxDDDepthFunc( ctx, GL_EQUAL );
+ break;
+ }
+
+ fxDDDepthMask( ctx, GL_FALSE );
+ }
+
+ if (ctx->Texture.Unit[1].EnvMode == GL_MODULATE) {
+ fxDDEnable( ctx, GL_BLEND, GL_TRUE );
+ fxDDBlendFunc( ctx, GL_DST_COLOR, GL_ZERO );
+ }
+
+ fxSetupTextureSingleTMU( ctx, 1 );
+ fxSetupBlend( ctx );
+ fxSetupDepthTest( ctx );
+ break;
+
+ case 2:
+ /* Restore original state.
+ */
+ fxMesa->tmu_source[0] = 0;
+ fxMesa->unitsState = fxMesa->restoreUnitsState;
+ fxMesa->setupdone &= ~SETUP_TMU0;
+ fxSetupTextureSingleTMU( ctx, 0 );
+ fxSetupBlend( ctx );
+ fxSetupDepthTest( ctx );
+ break;
+ }
+
+ return pass == 1;
+}
+
+
+/************************************************************************/
+/************************** Changes to units state **********************/
+/************************************************************************/
+
+
+/* All units setup is handled under texture setup.
+ */
+void fxDDShadeModel(GLcontext *ctx, GLenum mode)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+
+
+/************************************************************************/
+/****************************** Units SetUp *****************************/
+/************************************************************************/
+void gl_print_fx_state_flags( const char *msg, GLuint flags )
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & FX_NEW_TEXTURING) ? "texture, " : "",
+ (flags & FX_NEW_BLEND) ? "blend, " : "",
+ (flags & FX_NEW_ALPHA) ? "alpha, " : "",
+ (flags & FX_NEW_FOG) ? "fog, " : "",
+ (flags & FX_NEW_SCISSOR) ? "scissor, " : "",
+ (flags & FX_NEW_COLOR_MASK) ? "colormask, " : "",
+ (flags & FX_NEW_CULL) ? "cull, " : "");
+}
+
+void fxSetupFXUnits( GLcontext *ctx )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint newstate = fxMesa->new_state;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ gl_print_fx_state_flags("fxmesa: fxSetupFXUnits", newstate);
+
+ if (newstate) {
+ if (newstate & FX_NEW_TEXTURING)
+ fxSetupTexture(ctx);
+
+ if (newstate & FX_NEW_BLEND)
+ fxSetupBlend(ctx);
+
+ if (newstate & FX_NEW_ALPHA)
+ fxSetupAlphaTest(ctx);
+
+ if (newstate & FX_NEW_DEPTH)
+ fxSetupDepthTest(ctx);
+
+ if (newstate & FX_NEW_FOG)
+ fxSetupFog(ctx,GL_FALSE);
+
+ if (newstate & FX_NEW_SCISSOR)
+ fxSetupScissor(ctx);
+
+ if (newstate & FX_NEW_COLOR_MASK)
+ fxSetupColorMask(ctx);
+
+ if (newstate & FX_NEW_CULL)
+ fxSetupCull(ctx);
+
+ fxMesa->new_state = 0;
+ ctx->Driver.RenderStart = 0;
+ }
+}
+
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_setup(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxtexman.c b/src/mesa/drivers/glide/fxtexman.c
new file mode 100644
index 0000000000..5ee145e3cb
--- /dev/null
+++ b/src/mesa/drivers/glide/fxtexman.c
@@ -0,0 +1,579 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxtexman.c - 3Dfx VooDoo texture memory functions
+*/
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+
+static tfxTMFreeNode *fxTMNewTMFreeNode(FxU32 start, FxU32 end)
+{
+ tfxTMFreeNode *tmn;
+
+ if(!(tmn=malloc(sizeof(tfxTMFreeNode)))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmn->next=NULL;
+ tmn->startAddress=start;
+ tmn->endAddress=end;
+
+ return tmn;
+}
+
+static void fxTMUInit(fxMesaContext fxMesa, int tmu)
+{
+ tfxTMFreeNode *tmn,*tmntmp;
+ FxU32 start,end,blockstart,blockend;
+
+ start=grTexMinAddress(tmu);
+ end=grTexMaxAddress(tmu);
+
+ if(fxMesa->verbose) {
+ fprintf(stderr,"%s configuration:",(tmu==FX_TMU0) ? "TMU0" : "TMU1");
+ fprintf(stderr," Lower texture memory address (%u)\n",(unsigned int)start);
+ fprintf(stderr," Higher texture memory address (%u)\n",(unsigned int)end);
+ fprintf(stderr," Splitting Texture memory in 2Mb blocks:\n");
+ }
+
+ fxMesa->freeTexMem[tmu]=end-start;
+ fxMesa->tmFree[tmu]=NULL;
+ fxMesa->tmAlloc[tmu]=NULL;
+
+ blockstart=start;
+ while(blockstart<=end) {
+ if(blockstart+0x1fffff>end)
+ blockend=end;
+ else
+ blockend=blockstart+0x1fffff;
+
+ if(fxMesa->verbose)
+ fprintf(stderr," %07u-%07u\n",(unsigned int)blockstart,(unsigned int)blockend);
+
+ tmn=fxTMNewTMFreeNode(blockstart,blockend);
+
+ if(fxMesa->tmFree[tmu]) {
+ for(tmntmp=fxMesa->tmFree[tmu];tmntmp->next!=NULL;tmntmp=tmntmp->next){};
+ tmntmp->next=tmn;
+ } else
+ fxMesa->tmFree[tmu]=tmn;
+
+ blockstart+=0x1fffff+1;
+ }
+}
+
+void fxTMInit(fxMesaContext fxMesa)
+{
+ fxTMUInit(fxMesa,FX_TMU0);
+
+ if(fxMesa->haveTwoTMUs)
+ fxTMUInit(fxMesa,FX_TMU1);
+
+ fxMesa->texBindNumber=0;
+}
+
+static struct gl_texture_object *fxTMFindOldestTMBlock(fxMesaContext fxMesa,
+ tfxTMAllocNode *tmalloc,
+ GLuint texbindnumber)
+{
+ GLuint age,oldestage,lasttimeused;
+ struct gl_texture_object *oldesttexobj;
+
+ (void)fxMesa;
+ oldesttexobj=tmalloc->tObj;
+ oldestage=0;
+
+ while(tmalloc) {
+ lasttimeused=((tfxTexInfo *)(tmalloc->tObj->DriverData))->tmi.lastTimeUsed;
+
+ if(lasttimeused>texbindnumber)
+ age=texbindnumber+(UINT_MAX-lasttimeused+1); /* TO DO: check */
+ else
+ age=texbindnumber-lasttimeused;
+
+ if(age>=oldestage) {
+ oldestage=age;
+ oldesttexobj=tmalloc->tObj;
+ }
+
+ tmalloc=tmalloc->next;
+ }
+
+ return oldesttexobj;
+}
+
+static GLboolean fxTMFreeOldTMBlock(fxMesaContext fxMesa, GLint tmu)
+{
+ struct gl_texture_object *oldesttexobj;
+
+ if(!fxMesa->tmAlloc[tmu])
+ return GL_FALSE;
+
+ oldesttexobj=fxTMFindOldestTMBlock(fxMesa,fxMesa->tmAlloc[tmu],fxMesa->texBindNumber);
+
+ fxTMMoveOutTM(fxMesa,oldesttexobj);
+
+ return GL_TRUE;
+}
+
+static tfxTMFreeNode *fxTMExtractTMFreeBlock(tfxTMFreeNode *tmfree, int texmemsize,
+ GLboolean *success, FxU32 *startadr)
+{
+ int blocksize;
+
+ /* TO DO: cut recursion */
+
+ if(!tmfree) {
+ *success=GL_FALSE;
+ return NULL;
+ }
+
+ blocksize=(int)tmfree->endAddress-(int)tmfree->startAddress+1;
+
+ if(blocksize==texmemsize) {
+ tfxTMFreeNode *nexttmfree;
+
+ *success=GL_TRUE;
+ *startadr=tmfree->startAddress;
+
+ nexttmfree=tmfree->next;
+ free(tmfree);
+
+ return nexttmfree;
+ }
+
+ if(blocksize>texmemsize) {
+ *success=GL_TRUE;
+ *startadr=tmfree->startAddress;
+
+ tmfree->startAddress+=texmemsize;
+
+ return tmfree;
+ }
+
+ tmfree->next=fxTMExtractTMFreeBlock(tmfree->next,texmemsize,success,startadr);
+
+ return tmfree;
+}
+
+static tfxTMAllocNode *fxTMGetTMBlock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint tmu, int texmemsize)
+{
+ tfxTMFreeNode *newtmfree;
+ tfxTMAllocNode *newtmalloc;
+ GLboolean success;
+ FxU32 startadr;
+
+ for(;;) { /* TO DO: improve performaces */
+ newtmfree=fxTMExtractTMFreeBlock(fxMesa->tmFree[tmu],texmemsize,&success,&startadr);
+
+ if(success) {
+ fxMesa->tmFree[tmu]=newtmfree;
+
+ fxMesa->freeTexMem[tmu]-=texmemsize;
+
+ if(!(newtmalloc=malloc(sizeof(tfxTMAllocNode)))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ newtmalloc->next=fxMesa->tmAlloc[tmu];
+ newtmalloc->startAddress=startadr;
+ newtmalloc->endAddress=startadr+texmemsize-1;
+ newtmalloc->tObj=tObj;
+
+ fxMesa->tmAlloc[tmu]=newtmalloc;
+
+ return newtmalloc;
+ }
+
+ if(!fxTMFreeOldTMBlock(fxMesa,tmu)) {
+ fprintf(stderr,"fx Driver: internal error in fxTMGetTMBlock()\n");
+ fprintf(stderr," TMU: %d Size: %d\n",tmu,texmemsize);
+
+ fxCloseHardware();
+ exit(-1);
+ }
+ }
+}
+
+void fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint where)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ int i,l;
+ int texmemsize;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTMMoveInTM(%d)\n",tObj->Name);
+ }
+
+ fxMesa->stats.reqTexUpload++;
+
+ if(!ti->validated) {
+ fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ if(ti->tmi.isInTM)
+ return;
+
+ if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_TEXTURE)) {
+ fprintf(stderr,"fxmesa: downloading %x (%d) in texture memory in %d\n",(GLuint)tObj,tObj->Name,where);
+ }
+
+ ti->tmi.whichTMU=(FxU32)where;
+
+ switch(where) {
+ case FX_TMU0:
+ case FX_TMU1:
+ texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
+ ti->tmi.tm[where]=fxTMGetTMBlock(fxMesa,tObj,where,texmemsize);
+ fxMesa->stats.memTexUpload+=texmemsize;
+
+ for(i=FX_largeLodValue(ti->info),l=ti->minLevel;i<=FX_smallLodValue(ti->info);i++,l++)
+ grTexDownloadMipMapLevel(where,
+ ti->tmi.tm[where]->startAddress,FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
+ ti->tmi.mipmapLevel[l].data);
+ break;
+ case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+ texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD,&(ti->info));
+ ti->tmi.tm[FX_TMU0]=fxTMGetTMBlock(fxMesa,tObj,FX_TMU0,texmemsize);
+ fxMesa->stats.memTexUpload+=texmemsize;
+
+ texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN,&(ti->info));
+ ti->tmi.tm[FX_TMU1]=fxTMGetTMBlock(fxMesa,tObj,FX_TMU1,texmemsize);
+ fxMesa->stats.memTexUpload+=texmemsize;
+
+ for(i=FX_largeLodValue(ti->info),l=ti->minLevel;i<=FX_smallLodValue(ti->info);i++,l++) {
+ grTexDownloadMipMapLevel(GR_TMU0,ti->tmi.tm[FX_TMU0]->startAddress,FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_ODD,
+ ti->tmi.mipmapLevel[l].data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,ti->tmi.tm[FX_TMU1]->startAddress,FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
+ ti->tmi.mipmapLevel[l].data);
+ }
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",where);
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ fxMesa->stats.texUpload++;
+
+ ti->tmi.isInTM=GL_TRUE;
+}
+
+void fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint level)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ GrLOD_t lodlevel;
+ GLint tmu;
+
+ if(!ti->validated) {
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu=(int)ti->tmi.whichTMU;
+ fxTMMoveInTM(fxMesa,tObj,tmu);
+
+ fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height,
+ &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+
+ switch(tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevel(tmu,
+ ti->tmi.tm[tmu]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
+ ti->tmi.mipmapLevel[level].data);
+ break;
+ case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tmi.tm[GR_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_ODD,
+ ti->tmi.mipmapLevel[level].data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tmi.tm[GR_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
+ ti->tmi.mipmapLevel[level].data);
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+void fxTMReloadSubMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint level, GLint yoffset, GLint height)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ GrLOD_t lodlevel;
+ unsigned short *data;
+ GLint tmu;
+
+ if(!ti->validated) {
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu=(int)ti->tmi.whichTMU;
+ fxTMMoveInTM(fxMesa,tObj,tmu);
+
+ fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height,
+ &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+
+ if((ti->info.format==GR_TEXFMT_INTENSITY_8) ||
+ (ti->info.format==GR_TEXFMT_P_8) ||
+ (ti->info.format==GR_TEXFMT_ALPHA_8))
+ data=ti->tmi.mipmapLevel[level].data+((yoffset*ti->tmi.mipmapLevel[level].width)>>1);
+ else
+ data=ti->tmi.mipmapLevel[level].data+yoffset*ti->tmi.mipmapLevel[level].width;
+
+ switch(tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevelPartial(tmu,
+ ti->tmi.tm[tmu]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
+ data,
+ yoffset,yoffset+height-1);
+ break;
+ case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+ grTexDownloadMipMapLevelPartial(GR_TMU0,
+ ti->tmi.tm[FX_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_ODD,
+ data,
+ yoffset,yoffset+height-1);
+
+ grTexDownloadMipMapLevelPartial(GR_TMU1,
+ ti->tmi.tm[FX_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
+ data,
+ yoffset,yoffset+height-1);
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+static tfxTMAllocNode *fxTMFreeTMAllocBlock(tfxTMAllocNode *tmalloc,
+ tfxTMAllocNode *tmunalloc)
+{
+ if(!tmalloc)
+ return NULL;
+
+ if(tmalloc==tmunalloc) {
+ tfxTMAllocNode *newtmalloc;
+
+ newtmalloc=tmalloc->next;
+ free(tmalloc);
+
+ return newtmalloc;
+ }
+
+ tmalloc->next=fxTMFreeTMAllocBlock(tmalloc->next,tmunalloc);
+
+ return tmalloc;
+}
+
+static tfxTMFreeNode *fxTMAddTMFree(tfxTMFreeNode *tmfree, FxU32 startadr, FxU32 endadr)
+{
+ if(!tmfree)
+ return fxTMNewTMFreeNode(startadr,endadr);
+
+ if((endadr+1==tmfree->startAddress) && (tmfree->startAddress & 0x1fffff)) {
+ tmfree->startAddress=startadr;
+
+ return tmfree;
+ }
+
+ if((startadr-1==tmfree->endAddress) && (startadr & 0x1fffff)) {
+ tmfree->endAddress=endadr;
+
+ if((tmfree->next && (endadr+1==tmfree->next->startAddress) &&
+ (tmfree->next->startAddress & 0x1fffff))) {
+ tfxTMFreeNode *nexttmfree;
+
+ tmfree->endAddress=tmfree->next->endAddress;
+
+ nexttmfree=tmfree->next->next;
+ free(tmfree->next);
+
+ tmfree->next=nexttmfree;
+ }
+
+
+ return tmfree;
+ }
+
+ if(startadr<tmfree->startAddress) {
+ tfxTMFreeNode *newtmfree;
+
+ newtmfree=fxTMNewTMFreeNode(startadr,endadr);
+ newtmfree->next=tmfree;
+
+ return newtmfree;
+ }
+
+ tmfree->next=fxTMAddTMFree(tmfree->next,startadr,endadr);
+
+ return tmfree;
+}
+
+static void fxTMFreeTMBlock(fxMesaContext fxMesa, GLint tmu, tfxTMAllocNode *tmalloc)
+{
+ FxU32 startadr,endadr;
+
+ startadr=tmalloc->startAddress;
+ endadr=tmalloc->endAddress;
+
+ fxMesa->tmAlloc[tmu]=fxTMFreeTMAllocBlock(fxMesa->tmAlloc[tmu],tmalloc);
+
+ fxMesa->tmFree[tmu]=fxTMAddTMFree(fxMesa->tmFree[tmu],startadr,endadr);
+
+ fxMesa->freeTexMem[tmu]+=endadr-startadr+1;
+}
+
+void fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTMMoveOutTM(%x (%d))\n",(GLuint)tObj,tObj->Name);
+ }
+
+ if(!ti->tmi.isInTM)
+ return;
+
+ switch(ti->tmi.whichTMU) {
+ case FX_TMU0:
+ case FX_TMU1:
+ fxTMFreeTMBlock(fxMesa,(int)ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]);
+ break;
+ case FX_TMU_SPLIT:
+ fxTMFreeTMBlock(fxMesa,FX_TMU0,ti->tmi.tm[FX_TMU0]);
+ fxTMFreeTMBlock(fxMesa,FX_TMU1,ti->tmi.tm[FX_TMU1]);
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMMoveOutTM()\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ ti->tmi.whichTMU=FX_TMU_NONE;
+ ti->tmi.isInTM=GL_FALSE;
+}
+
+void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ int i;
+
+ fxTMMoveOutTM(fxMesa,tObj);
+
+ for(i=0;i<MAX_TEXTURE_LEVELS;i++) {
+ if(ti->tmi.mipmapLevel[i].used &&
+ ti->tmi.mipmapLevel[i].translated)
+ free(ti->tmi.mipmapLevel[i].data);
+
+ (void)ti->tmi.mipmapLevel[i].data;
+ }
+}
+
+void fxTMFreeAllFreeNode(tfxTMFreeNode *fn)
+{
+ if(!fn)
+ return;
+
+ if(fn->next)
+ fxTMFreeAllFreeNode(fn->next);
+
+ free(fn);
+}
+
+void fxTMFreeAllAllocNode(tfxTMAllocNode *an)
+{
+ if(!an)
+ return;
+
+ if(an->next)
+ fxTMFreeAllAllocNode(an->next);
+
+ free(an);
+}
+
+void fxTMClose(fxMesaContext fxMesa)
+{
+ fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU0]);
+ fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU0]);
+ fxMesa->tmFree[FX_TMU0] = NULL;
+ fxMesa->tmAlloc[FX_TMU0] = NULL;
+ if(fxMesa->haveTwoTMUs) {
+ fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU1]);
+ fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU1]);
+ fxMesa->tmFree[FX_TMU1] = NULL;
+ fxMesa->tmAlloc[FX_TMU1] = NULL;
+ }
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_texman(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxwgl.c b/src/mesa/drivers/glide/fxwgl.c
new file mode 100644
index 0000000000..cbea79aecd
--- /dev/null
+++ b/src/mesa/drivers/glide/fxwgl.c
@@ -0,0 +1,806 @@
+/* fxwgl.c - Microsoft wgl functions emulation for
+ * 3Dfx VooDoo/Mesa interface
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef __WIN32__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#ifdef __cplusplus
+ }
+#endif
+
+#include <stdio.h>
+#include <GL/fxmesa.h>
+#include "fxdrv.h"
+
+#define MAX_MESA_ATTRS 20
+
+struct __extensions__
+{
+ PROC proc;
+ char *name;
+};
+
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLint mesaAttr[MAX_MESA_ATTRS];
+};
+
+WINGDIAPI void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *);
+
+static struct __extensions__ ext[] = {
+
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)gl3DfxSetPaletteEXT, "3DFX_set_global_palette" },
+ { (PROC)glColorTableEXT, "glColorTableEXT" },
+ { (PROC)glColorSubTableEXT, "glColorSubTableEXT" },
+ { (PROC)glGetColorTableEXT, "glGetColorTableEXT" },
+ { (PROC)glGetColorTableParameterfvEXT, "glGetColorTableParameterfvEXT" },
+ { (PROC)glGetColorTableParameterivEXT, "glGetColorTableParameterivEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+ { (PROC)glBlendFuncSeparateINGR, "glBlendFuncSeparateINGR" },
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }
+};
+
+static int qt_ext = sizeof(ext) / sizeof(ext[0]);
+
+struct __pixelformat__ pix[] =
+{
+ /* None */
+ {
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
+ PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 32,
+ 8,0,8,8,8,16,0,24,
+ 0,0,0,0,0,
+ 0,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,0,0,0
+ },
+ {
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 0,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE
+ }
+ },
+
+ /* Alpha */
+ {
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
+ PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 32,
+ 8,0,8,8,8,16,8,24,
+ 0,0,0,0,0,
+ 0,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,0,0,0
+ },
+ {
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 8,
+ FXMESA_DEPTH_SIZE, 0,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE
+ }
+ },
+
+ /* Depth */
+ {
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
+ PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 32,
+ 8,0,8,8,8,16,0,24,
+ 0,0,0,0,0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,0,0,0
+ },
+ {
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE
+ }
+ }
+};
+static int qt_pix = sizeof(pix) / sizeof(pix[0]);
+
+static fxMesaContext ctx = NULL;
+static WNDPROC hWNDOldProc;
+static int curPFD = 0;
+static HDC hDC;
+static HWND hWND;
+
+static GLboolean haveDualHead;
+
+/* For the in-window-rendering hack */
+
+static GLboolean gdiWindowHack;
+static GLboolean gdiWindowHackEna;
+static void *dibSurfacePtr;
+static BITMAPINFO *dibBMI;
+static HBITMAP dibHBM;
+static HWND dibWnd;
+
+LONG GLAPIENTRY __wglMonitor(HWND hwnd,UINT message,UINT wParam,LONG lParam)
+
+{
+ long ret; /* Now gives the resized window at the end to hWNDOldProc */
+
+ if(ctx && hwnd == hWND) {
+ switch(message) {
+ case WM_PAINT:
+ case WM_MOVE:
+ break;
+ case WM_DISPLAYCHANGE:
+ case WM_SIZE:
+ if (wParam != SIZE_MINIMIZED) {
+ static int moving = 0;
+ if (!moving) {
+ if(fxQueryHardware()!=GR_SSTTYPE_VOODOO) {
+ if(!grSstControl(GR_CONTROL_RESIZE)) {
+ moving = 1;
+ SetWindowPos(hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER);
+ moving = 0;
+ if(!grSstControl(GR_CONTROL_RESIZE)) {
+ /*MessageBox(0,_T("Error changing windowsize"),_T("fxMESA"),MB_OK);*/
+ PostMessage(hWND,WM_CLOSE,0,0);
+ }
+ }
+ }
+
+ /* Do the clipping in the glide library */
+ grClipWindow(0,0,grSstScreenWidth(),grSstScreenHeight());
+ /* And let the new size set in the context */
+ fxMesaUpdateScreenSize(ctx);
+ }
+ }
+ break;
+ case WM_ACTIVATE:
+ if((fxQueryHardware()==GR_SSTTYPE_VOODOO) &&
+ (!gdiWindowHack) &&
+ (!haveDualHead)) {
+ WORD fActive = LOWORD(wParam);
+ BOOL fMinimized = (BOOL) HIWORD(wParam);
+
+ if((fActive == WA_INACTIVE) || fMinimized)
+ grSstControl(GR_CONTROL_DEACTIVATE);
+ else
+ grSstControl(GR_CONTROL_ACTIVATE);
+ }
+ break;
+ case WM_SHOWWINDOW:
+ break;
+ case WM_SYSCHAR:
+ if(gdiWindowHackEna && (VK_RETURN == wParam)) {
+ if(gdiWindowHack) {
+ gdiWindowHack = GL_FALSE;
+ grSstControl(GR_CONTROL_ACTIVATE);
+ } else {
+ gdiWindowHack = GL_TRUE;
+ grSstControl(GR_CONTROL_DEACTIVATE);
+ }
+ }
+ break;
+ }
+ }
+
+ /* Finaly call the hWNDOldProc, which handles the resize witch the
+ now changed window sizes */
+ ret = CallWindowProc( hWNDOldProc, hwnd, message, wParam, lParam );
+
+ return(ret);
+}
+
+BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
+{
+ return(FALSE);
+}
+
+HGLRC GLAPIENTRY wglCreateContext(HDC hdc)
+{
+ HWND hWnd;
+ WNDPROC oldProc;
+ int error;
+
+ if(ctx) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ if(!(hWnd = WindowFromDC(hdc))) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ if(curPFD == 0) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ if((oldProc = (WNDPROC)GetWindowLong(hWnd,GWL_WNDPROC)) != __wglMonitor) {
+ hWNDOldProc = oldProc;
+ SetWindowLong(hWnd,GWL_WNDPROC,(LONG)__wglMonitor);
+ }
+
+#ifndef FX_SILENT
+ freopen("MESA.LOG","w",stderr);
+#endif
+
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ SetForegroundWindow(hWnd);
+ Sleep(100); /* an hack for win95 */
+
+ if(fxQueryHardware() == GR_SSTTYPE_VOODOO) {
+ RECT cliRect;
+
+ GetClientRect(hWnd,&cliRect);
+ error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom,
+ pix[curPFD - 1].mesaAttr));
+
+ if(!error) {
+ /* create the DIB section for windowed rendering */
+ DWORD *p;
+
+ dibWnd = hWnd;
+
+ hDC = GetDC(dibWnd);
+
+ dibBMI = (BITMAPINFO*) malloc( sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD)));
+
+ memset(dibBMI,0,sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD)));
+
+ dibBMI->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dibBMI->bmiHeader.biWidth = ctx->width;
+ dibBMI->bmiHeader.biHeight = -ctx->height;
+ dibBMI->bmiHeader.biPlanes = (short)1;
+ dibBMI->bmiHeader.biBitCount = (short)16;
+ dibBMI->bmiHeader.biCompression = BI_BITFIELDS;
+ dibBMI->bmiHeader.biSizeImage = 0;
+ dibBMI->bmiHeader.biXPelsPerMeter = 0;
+ dibBMI->bmiHeader.biYPelsPerMeter = 0;
+ dibBMI->bmiHeader.biClrUsed = 3;
+ dibBMI->bmiHeader.biClrImportant = 3;
+
+ p = (DWORD*)dibBMI->bmiColors;
+ p[0] = 0xF800;
+ p[1] = 0x07E0;
+ p[2] = 0x001F;
+
+ dibHBM = CreateDIBSection(hDC, dibBMI, DIB_RGB_COLORS, &dibSurfacePtr, NULL, 0);
+
+ ReleaseDC(dibWnd, hDC);
+
+ gdiWindowHackEna = (dibHBM != NULL ? GL_TRUE : GL_FALSE);
+
+ if (!getenv("MESA_WGL_FX") || !strcmp(getenv("MESA_WGL_FX"),"fullscreen"))
+ gdiWindowHack = GL_FALSE;
+ else {
+ gdiWindowHack = GL_TRUE;
+ grSstControl(GR_CONTROL_DEACTIVATE);
+ }
+ }
+ } else {
+ /* For the Voodoo Rush */
+
+ if(getenv("MESA_WGL_FX") && !strcmp(getenv("MESA_WGL_FX"),"fullscreen")) {
+ RECT cliRect;
+
+ GetClientRect(hWnd,&cliRect);
+ error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom,
+ pix[curPFD - 1].mesaAttr));
+ } else
+ error = !(ctx = fxMesaCreateContext((GLuint)hWnd,GR_RESOLUTION_NONE,GR_REFRESH_75Hz,
+ pix[curPFD - 1].mesaAttr));
+ }
+
+ if(getenv("SST_DUALHEAD"))
+ haveDualHead=((atoi(getenv("SST_DUALHEAD"))==1) ? GL_TRUE:GL_FALSE);
+ else
+ haveDualHead=GL_FALSE;
+
+ if(error) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ hDC = hdc;
+ hWND = hWnd;
+
+ /* Required by the OpenGL Optimizer 1.1 (is it a Optimizer bug ?) */
+ wglMakeCurrent(hdc,(HGLRC)1);
+
+ return((HGLRC)1);
+}
+
+HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,int iLayerPlane)
+{
+ SetLastError(0);
+ return(NULL);
+}
+
+BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc)
+{
+ if(ctx && hglrc == (HGLRC)1) {
+ if (gdiWindowHackEna) {
+ DeleteObject(dibHBM);
+ free(dibBMI);
+
+ dibSurfacePtr = NULL;
+ dibBMI = NULL;
+ dibHBM = NULL;
+ dibWnd = NULL;
+ }
+
+ fxMesaDestroyContext(ctx);
+
+ SetWindowLong(WindowFromDC(hDC),GWL_WNDPROC,(LONG)hWNDOldProc);
+
+ ctx = NULL;
+ hDC = 0;
+ return(TRUE);
+ }
+
+ SetLastError(0);
+
+ return(FALSE);
+}
+
+HGLRC GLAPIENTRY wglGetCurrentContext(VOID)
+{
+ if(ctx)
+ return((HGLRC)1);
+
+ SetLastError(0);
+ return(NULL);
+}
+
+HDC GLAPIENTRY wglGetCurrentDC(VOID)
+{
+ if(ctx)
+ return(hDC);
+
+ SetLastError(0);
+ return(NULL);
+}
+
+PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc)
+{
+ int i;
+
+ /*fprintf(stderr,"fxMesa: looking for extension %s\n",lpszProc);
+ fflush(stderr);*/
+
+ for(i = 0;i < qt_ext;i++)
+ if(!strcmp(lpszProc,ext[i].name)) {
+ /*fprintf(stderr,"fxMesa: found extension %s\n",lpszProc);
+ fflush(stderr);*/
+
+ return(ext[i].proc);
+ }
+ SetLastError(0);
+ return(NULL);
+}
+
+BOOL GLAPIENTRY wglMakeCurrent(HDC hdc,HGLRC hglrc)
+{
+ if((hdc==NULL) && (hglrc==NULL))
+ return(TRUE);
+
+ if(!ctx || hglrc != (HGLRC)1 || WindowFromDC(hdc) != hWND) {
+ SetLastError(0);
+ return(FALSE);
+ }
+
+ hDC = hdc;
+
+ fxMesaMakeCurrent(ctx);
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,HGLRC hglrc2)
+{
+ if(!ctx || hglrc1 != (HGLRC)1 || hglrc1 != hglrc2) {
+ SetLastError(0);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY wglUseFontBitmaps(HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase)
+{
+#define VERIFY(a) a
+
+ TEXTMETRIC metric;
+ BITMAPINFO *dibInfo;
+ HDC bitDevice;
+ COLORREF tempColor;
+ int i;
+
+ VERIFY(GetTextMetrics(fontDevice, &metric));
+
+ dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1);
+ dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dibInfo->bmiHeader.biPlanes = 1;
+ dibInfo->bmiHeader.biBitCount = 1;
+ dibInfo->bmiHeader.biCompression = BI_RGB;
+
+ bitDevice = CreateCompatibleDC(fontDevice);
+ // HDC bitDevice = CreateDC("DISPLAY", NULL, NULL, NULL);
+ // VERIFY(bitDevice);
+
+ // Swap fore and back colors so the bitmap has the right polarity
+ tempColor = GetBkColor(bitDevice);
+ SetBkColor(bitDevice, GetTextColor(bitDevice));
+ SetTextColor(bitDevice, tempColor);
+
+ // Place chars based on base line
+ VERIFY(SetTextAlign(bitDevice, TA_BASELINE) >= 0);
+
+ for(i = 0; i < numChars; i++) {
+ SIZE size;
+ char curChar;
+ int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res;
+ HBITMAP bitObject;
+ HGDIOBJ origBmap;
+ unsigned char *bmap;
+
+ curChar = i + firstChar;
+
+ // Find how high/wide this character is
+ VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size));
+
+ // Create the output bitmap
+ charWidth = size.cx;
+ charHeight = size.cy;
+ bmapWidth = ((charWidth + 31) / 32) * 32; // Round up to the next multiple of 32 bits
+ bmapHeight = charHeight;
+ bitObject = CreateCompatibleBitmap(bitDevice,
+ bmapWidth,
+ bmapHeight);
+ //VERIFY(bitObject);
+
+ // Assign the output bitmap to the device
+ origBmap = SelectObject(bitDevice, bitObject);
+ VERIFY(origBmap);
+
+ VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) );
+
+ // Use our source font on the device
+ VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT)));
+
+ // Draw the character
+ VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1));
+
+ // Unselect our bmap object
+ VERIFY(SelectObject(bitDevice, origBmap));
+
+ // Convert the display dependant representation to a 1 bit deep DIB
+ numBytes = (bmapWidth * bmapHeight) / 8;
+ bmap = malloc(numBytes);
+ dibInfo->bmiHeader.biWidth = bmapWidth;
+ dibInfo->bmiHeader.biHeight = bmapHeight;
+ res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap,
+ dibInfo,
+ DIB_RGB_COLORS);
+ //VERIFY(res);
+
+ // Create the GL object
+ glNewList(i + listBase, GL_COMPILE);
+ glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent,
+ charWidth, 0.0,
+ bmap);
+ glEndList();
+ // CheckGL();
+
+ // Destroy the bmap object
+ DeleteObject(bitObject);
+
+ // Deallocate the bitmap data
+ free(bmap);
+ }
+
+ // Destroy the DC
+ VERIFY(DeleteDC(bitDevice));
+
+ free(dibInfo);
+
+ return TRUE;
+#undef VERIFY
+}
+
+BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase)
+{
+ return(FALSE);
+}
+
+BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+
+BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,UINT fuPlanes)
+{
+ if(ctx && WindowFromDC(hdc) == hWND) {
+ fxMesaSwapBuffers();
+
+ return(TRUE);
+ }
+
+ SetLastError(0);
+ return(FALSE);
+}
+
+int GLAPIENTRY wglChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int i,best=-1,qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+
+ if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) {
+ SetLastError(0);
+ return(0);
+ }
+
+ for(i = 0;i < qt_valid_pix;i++) {
+ if((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
+ continue;
+ if((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
+ continue;
+ if((ppfd->dwFlags & PFD_SUPPORT_GDI) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI))
+ continue;
+ if((ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
+ continue;
+ if(!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
+ continue;
+ if(!(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO)))
+ continue;
+
+ if (ppfd->cDepthBits > 0 && pix[i].pfd.cDepthBits == 0)
+ continue; /* need depth buffer */
+
+ if (ppfd->cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0)
+ continue; /* need alpha buffer */
+
+ if(ppfd->iPixelType == pix[i].pfd.iPixelType) {
+ best = i + 1;
+ break;
+ }
+ }
+
+ if(best == -1) {
+ SetLastError(0);
+ return(0);
+ }
+
+ return(best);
+}
+
+int GLAPIENTRY ChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ return wglChoosePixelFormat(hdc,ppfd);
+}
+
+int GLAPIENTRY wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix ||
+ ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) {
+ SetLastError(0);
+ return(0);
+ }
+
+ if(nBytes != 0)
+ *ppfd = pix[iPixelFormat - 1].pfd;
+
+ return(qt_valid_pix);
+}
+
+int GLAPIENTRY DescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ return wglDescribePixelFormat(hdc,iPixelFormat,nBytes,ppfd);
+}
+
+int GLAPIENTRY wglGetPixelFormat(HDC hdc)
+{
+ if(curPFD == 0) {
+ SetLastError(0);
+ return(0);
+ }
+
+ return(curPFD);
+}
+
+int GLAPIENTRY GetPixelFormat(HDC hdc)
+{
+ return wglGetPixelFormat(hdc);
+}
+
+BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ SetLastError(0);
+ return(FALSE);
+ }
+ curPFD = iPixelFormat;
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY wglSwapBuffers(HDC hdc)
+{
+ if(!ctx) {
+ SetLastError(0);
+ return(FALSE);
+ }
+
+ fxMesaSwapBuffers();
+
+ if(gdiWindowHack) {
+ GLuint width=ctx->width;
+ GLuint height=ctx->height;
+
+ HDC hdcScreen = GetDC(dibWnd);
+ HDC hdcDIBSection = CreateCompatibleDC(hdcScreen);
+ HBITMAP holdBitmap = (HBITMAP) SelectObject(hdcDIBSection, dibHBM);
+
+ grLfbReadRegion(GR_BUFFER_FRONTBUFFER, 0, 0,
+ width, height,
+ width * 2,
+ dibSurfacePtr);
+
+ /* Since the hardware is configured for GR_COLORFORMAT_ABGR the pixel data is
+ * going to come out as BGR 565, which is reverse of what we need for blitting
+ * to screen, so we need to convert it here pixel-by-pixel (ick). This loop would NOT
+ * be required if the color format was changed to GR_COLORFORMAT_ARGB, but I do
+ * not know the ramifications of that, so this will work until that is resolved.
+ *
+ * This routine CRIES out for MMX implementation, however since that's not
+ * guaranteed to be running on MMX enabled hardware so I'm not going to do
+ * that. I'm just going to try to make a reasonably efficient C
+ * version. -TAJ
+ *
+ * This routine drops frame rate by <1 fps on a 200Mhz MMX processor with a 640x480
+ * display. Obviously, it's performance hit will be higher on larger displays and
+ * less on smaller displays. To support the window-hack display this is probably fine.
+ */
+ {
+ unsigned long *pixel = dibSurfacePtr;
+ unsigned long count = (width * height) / 2;
+
+ while (count--)
+ {
+ *pixel++ = (*pixel & 0x07e007e0) /* greens */
+ | ((*pixel & 0xf800f800) >> 11) /* swap blues */
+ | ((*pixel & 0x001f001f) << 11) /* swap reds */
+ ;
+ }
+ }
+
+ BitBlt(hdcScreen, 0, 0,
+ width, height,
+ hdcDIBSection,
+ 0, 0, SRCCOPY);
+
+ ReleaseDC(dibWnd, hdcScreen);
+ SelectObject(hdcDIBSection, holdBitmap);
+ DeleteDC(hdcDIBSection);
+ }
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY SetPixelFormat(HDC hdc, int iPixelFormat,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ return wglSetPixelFormat(hdc,iPixelFormat,ppfd);
+}
+
+BOOL GLAPIENTRY SwapBuffers(HDC hdc)
+{
+ return wglSwapBuffers(hdc);
+}
+
+#endif /* FX */