home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / fxmesa1.c < prev    next >
Encoding:
Text File  |  1998-01-31  |  61.6 KB  |  2,314 lines

  1. /* -*- mode: C; tab-width:8;  -*-
  2.  
  3.              fxmesa1.c - 3Dfx VooDoo/Mesa interface
  4. */
  5.  
  6. /*
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Library General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Library General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Library General Public
  18.  * License along with this library; if not, write to the Free
  19.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  * Brian Paul  Nov 13, 1997
  22.  *         - fixed bug in read_color_span(), red/blue were swapped
  23.  *
  24.  * V0.20 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  25.  *         - written the closetmmanger() function in order to free all the memory
  26.  *           allocated by the Texture Memory Manager (it will be useful
  27.  *           when the support for multiple contexts/boards will be ready)
  28.  *         - now the Voodoo driver runs without printing any information,
  29.  *           define the env. var. MESA_FX_INFO if you want to read some
  30.  *           information about the hardware and some statistic
  31.  *         - written a small workaround for the "GLQuake multiplayer white box bug"
  32.  *           in the setup_fx_units() functions. I'm already rewriting
  33.  *           this function because it is the source of nearly all the current
  34.  *           Voodoo driver problems
  35.  *         - fixed the GLQuake texture misalignment problem (the texture
  36.  *           coordinates must be scaled between 0.0 and 256.0 and not
  37.  *           between 0.0 and 255.0)
  38.  *         - written the support for the GL_EXT_shared_texture_palette
  39.  *         - some small change for supporting the automatic bulding of the
  40.  *           OpenGL32.dll under the Windows platform
  41.  *         - the redefinition of a mipmap level is now a LOT faster. This path
  42.  *           is used by GLQuake for dynamic lighting with some call to glTexSubImage2D()
  43.  *         - the texture memory is now managed a set of 2MB blocks so
  44.  *           texture maps can't be allocated on a 2MB boundary. The new Pure3D
  45.  *           needs this kind of support (and probably any other Voodoo Graphics
  46.  *           board with more than 2MB of texture memory)
  47.  *
  48.  *         Brian Paul (brianp@elastic.avid.com) Avid Technology
  49.  *         - added write_monocolor_span(), fixed bug in write_color_span()
  50.  *         - added test for stenciling in choosepoint/line/triangle functions
  51.  *
  52.  *         Joe Waters (falc@attila.aegistech.com) Aegis
  53.  *         - written the support for the env. var. SST_SCREENREFRESH
  54.  *
  55.  * V0.19 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  56.  *         - written the 3Dfx Global Palette extension for GLQuake
  57.  *         - written the support for the GL_EXT_paletted_texture (it works only with GL_RGBA
  58.  *           palettes and the alpha value is ignored ... this is a limitation of the
  59.  *           the current Glide version and Voodoo hardware)
  60.  *         - fixed the amount of memory allocated for 8bit textures
  61.  *         - merged the under construction v0.19 driver with the Mesa 2.5
  62.  *         - finally written the support for deleting textures
  63.  *         - introduced a new powerful texture memory manager: the texture memory
  64.  *           is used as a cache of the set of all defined texture maps. You can
  65.  *           now define several MB of texture maps also with a 2MB of texture memory
  66.  *           (the texture memory manager will do automatically all the swap out/swap in
  67.  *           work). The new texture memory manager has also
  68.  *           solved a lot of other bugs/no specs compliance/problems
  69.  *           related to the texture memory usage. The texture
  70.  *           manager code is inside the new fxmesa3.c file
  71.  *         - broken the fxmesa.c file in two files (fxmesa1.c and fxmesa2.c)
  72.  *           and done some code cleanup
  73.  *         - now is possible to redefine texture mipmap levels already defined
  74.  *         - fixed a problem with the amount of texture memory allocated for textures
  75.  *           with not all mipmap levels defined
  76.  *         - fixed a small problem with single buffer rendering
  77.  *
  78.  *         Brian Paul (brianp@elastic.avid.com) Avid Technology
  79.  *         - read/write_color_span() now use front/back buffer correctly
  80.  *         - create GLvisual with 5,6,5 bits per pixel, not 8,8,8
  81.  *         - removed a few ^M characters from fxmesa2.c file
  82.  *
  83.  * V0.18 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  84.  *         - the Mesa-2.4beta3 is finally using the driver quads support (the
  85.  *           previous Mesa versions have never taken any advantage from the quads support !)
  86.  *         - tested with the Glide 2.4 for Win
  87.  *         - ported all asm code to Linux
  88.  *         - ported the v0.18 to Linux (without asm code)
  89.  *         - back to Linux !!!
  90.  *         - optimized the SETUP macro (no more vertex snap for points and lines)
  91.  *         - optimized the SETUP macro (added one argument)
  92.  *         - the Mesa/Voodoo is now 20/30% for points, lines and small triangles !
  93.  *         - performance improvement setting VBSIZE to 72 
  94.  *         - the GrVertex texture code is now written in asm
  95.  *         - the GrVertex zbuffer code is now written in asm
  96.  *         - the GrVertex wbuffer code is now written in asm
  97.  *         - the GrVertex gouraud code is now written in asm
  98.  *         - the GrVertex snap code is now written in asm
  99.  *         - changed the 8bit compressed texture maps in 8bit palette texture maps
  100.  *           support (it has the some advantage of compressed texture maps without the
  101.  *           problem of a fixed NCC table for all mipmap levels)
  102.  *         - written the support for 8bit compressed texture maps (but texture maps with
  103.  *           more than one mipmap level aren't working fine)
  104.  *         - finnaly everthing is working fine in MesaQuake !
  105.  *         - fixed a bug in the computation of texture mapping coordinates (I have found
  106.  *           the bug thanks to MesaQuake !)
  107.  *         - written the GL_REPLACE support (mainly for MesaQuake)
  108.  *         - written the support for textures with not all mipmap levels defined
  109.  *         - rewritten all the Texture memory stuff
  110.  *         - written the MesaQuake support (define MESAQUAKE)
  111.  *         - working with a ZBuffer if glOrtho or not int the default glDepthRange,
  112.  *           otherwise working with the WBuffer
  113.  *         written the glDepthRange support
  114.  *
  115.  *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
  116.  *         - written the fxCloseHardware() and the fxQuaryHardware() (mainly
  117.  *           for the VoodooWGL emulator)
  118.  *
  119.  *         Brian Paul (brianp@elastic.avid.com) Avid Technology
  120.  *         - implemented read/write_color_span() so glRead/DrawPixels() works
  121.  *         - now needs Glide 2.3 or later.  Removed GLIDE_FULL_SCREEN and call to grSstOpen()
  122.  *
  123.  * V0.17 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  124.  *         - optimized the bitmap support (66% faster)
  125.  *         - tested with the Mesa 2.3beta2
  126.  *
  127.  *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
  128.  *         - solved a problem with the drawbitmap() and the Voodoo Rush
  129.  *           (GR_ORIGIN_LOWER_LEFT did not work with the Stingray)
  130.  *
  131.  *         Brian Paul (brianp@elastic.avid.com) Avid Technology
  132.  *         - linux stuff
  133.  *         - general code clean-up
  134.  *         - added attribList parameter to fxMesaCreateContext()
  135.  *         - single buffering works now
  136.  *         - VB colors are now GLubytes, removed ColorShift stuff
  137.  *
  138.  *         Paul Metzger
  139.  *         - linux stuff
  140.  *
  141.  * V0.16 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  142.  *         - written the quadfunc support (no performance improvement)
  143.  *         - written the support for the new Mesa 2.3beta1 driver interface (Wow ! It is faaaster)
  144.  *         - rewritten the glBitmap support for the Glide 2.3 (~35% slower !)
  145.  *         - written the glBitmap support for the most common case (fonts)
  146.  *
  147.  *         Jack Palevich
  148.  *         - Glide 2.3 porting
  149.  *
  150.  *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
  151.  *         - extended the fxMesaCreateContext() and fxMesaCreateBestContext()
  152.  *           functions in order to support also the Voodoo Rush
  153.  *         - tested with the Hercules Stingray 128/3D (The rendering in a window works !)
  154.  *
  155.  * V0.15 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  156.  *         - written the GL_LUMINANCE_ALPHA support
  157.  *         - written the GL_ALPHA support
  158.  *         - written the GL_LUMINANCE support
  159.  *         - now SETUP correctly set color for mono color sequences
  160.  *         - written the 9x1,10x1,...,1x9,1x10,... texture map ratio support
  161.  *         - written the no square texture map support
  162.  *         - the fog table is no more rebuilt inside setup_fx_units() each time
  163.  *
  164.  *         Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation
  165.  *         - written (not yet finished: no texture mapping) support for glOrtho
  166.  *         - some change to setup functions
  167.  *         - the fog support is now fully compatible with the standard OpenGL
  168.  *         - rewritten several parts of the driver in order to take
  169.  *           advantage of meshes (40% faster !!!)
  170.  *
  171.  * V0.14 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  172.  *         - now glAlphaFunc() works
  173.  *         - now glDepthMask() works
  174.  *         - solved a mipmap problem when using more than one texture
  175.  *         - moved ti, texid and wscale inside the fxMesaContext (now we can
  176.  *           easy support more ctx and more boards)
  177.  *         - the management of the fxMesaContext was completly broken !
  178.  *         - solved several problems about Alpha and texture Alpha
  179.  *         - 4 (RGBA) texture channels supported
  180.  *         - setting the default color to white
  181.  *
  182.  *         Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation
  183.  *         - small change to fxMesaCreateContext() and fxMesaMakeCurrent()
  184.  *         - written the fog support
  185.  *         - setting the default clear color to black
  186.  *         - written cleangraphics() for the onexit() function
  187.  *         - written fxMesaCreateBestContext()
  188.  *
  189.  * V0.13 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  190.  *         - now glBlendFunc() works for all glBlendFunc without DST_ALPHA
  191.  *           (because the alpha buffer is not yet implemented) 
  192.  *         - now fxMesaCreateContext() accept resolution and refresh rate
  193.  *         - fixed a bug for texture mapping: the w (alias z) must be set
  194.  *           also without depth buffer
  195.  *         - fixed a bug for texture image with width!=256
  196.  *         - written texparam()
  197.  *         - written all point, line and triangle functions for all possible supported
  198.  *           contexts and the driver is slight faster with points, lines and small triangles
  199.  *         - fixed a small bug in fx/fxmesa.h (glOrtho)
  200.  *
  201.  * V0.12 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  202.  *         - glDepthFunc supported
  203.  *         - introduced a trick to discover the far plane distance
  204.  *           (see fxMesaSetFar and fx/fxmesa.h)
  205.  *         - now the wbuffer works with homogeneous coordinate (and it
  206.  *           doesn't work with a glOrtho projection :)
  207.  *         - solved several problems with homogeneous coordinate and texture mapping
  208.  *         - fixed a bug in all line functions
  209.  *         - fixed a clear framebuffer bug
  210.  *         - solved a display list/teximg problem (but use
  211.  *           glBindTexture: it is several times faster)
  212.  *
  213.  * V0.11 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  214.  *         - introduced texture mapping support (not yet finished !)
  215.  *         - tested with Mesa2.2b6
  216.  *         - the driver is faster 
  217.  *         - written glFlush/glFinish
  218.  *         - the driver print a lot of info about the Glide lib
  219.  *
  220.  * v0.1  - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
  221.  *         - Initial revision
  222.  *
  223.  */
  224.  
  225. #if defined(FX)
  226.  
  227. #include <math.h>
  228. #include <stdio.h>
  229. #include <stdlib.h>
  230.  
  231. #include "fxdrv.h"
  232.  
  233. fxMesaContext CurrentfxMesaCtx=NULL;
  234.  
  235. /*
  236.  * Status of 3Dfx hardware initialization
  237.  */
  238.  
  239. static int glideInitialized = 0;
  240. static int _3dfxPresent = 0;
  241. static GrHwConfiguration hwconfig;
  242.  
  243.  
  244. /**********************************************************************/
  245. /*****                 Miscellaneous functions                    *****/
  246. /**********************************************************************/
  247.  
  248. /* return buffer size information */
  249. static void buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
  250. {
  251.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  252.  
  253. #if defined(DEBUG_FXMESA)
  254.   fprintf(stderr,"fxmesa: buffer_size(...)\n");
  255. #endif
  256.  
  257.   *width=fxMesa->width;
  258.   *height=fxMesa->height;
  259. }
  260.  
  261.  
  262. /* Set current drawing color */
  263. static void set_color(GLcontext *ctx, GLubyte red, GLubyte green,
  264.               GLubyte blue, GLubyte alpha )
  265. {
  266.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  267.  
  268. #if defined(DEBUG_FXMESA)
  269.   fprintf(stderr,"fxmesa: set_color(%d,%d,%d,%d)\n",red,green,blue,alpha);
  270. #endif
  271.  
  272.   fxMesa->color=FXCOLOR(red,green,blue,alpha);
  273. }
  274.  
  275.  
  276. /* implements glClearColor() */
  277. static void clear_color(GLcontext *ctx, GLubyte red, GLubyte green,
  278.             GLubyte blue, GLubyte alpha )
  279. {
  280.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  281.  
  282. #if defined(DEBUG_FXMESA)
  283.   fprintf(stderr,"fxmesa: clear_color(%d,%d,%d,%d)\n",red,green,blue,alpha);
  284. #endif
  285.  
  286.   fxMesa->clearc=FXCOLOR(red,green,blue,255);
  287.   fxMesa->cleara=alpha;
  288. }
  289.  
  290.  
  291. /* clear the frame buffer */
  292. static void clear(GLcontext *ctx, GLboolean all,
  293.           GLint x, GLint y, GLint width, GLint height )
  294. {
  295.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  296.  
  297. #if defined(DEBUG_FXMESA)
  298.   fprintf(stderr,"fxmesa: clear(%d,%d,%d,%d)\n",x,y,width,height);
  299. #endif
  300.  
  301.   grDepthMask(FXFALSE);
  302.  
  303.   grBufferClear(fxMesa->clearc,fxMesa->cleara,0);
  304.  
  305.   if(ctx->Depth.Test && ctx->Depth.Mask)
  306.     grDepthMask(FXTRUE);
  307. }
  308.  
  309.  
  310. /*  set the buffer used in double buffering */
  311. static GLboolean set_buffer(GLcontext *ctx, GLenum mode )
  312. {
  313.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  314. #if defined(DEBUG_FXMESA)
  315.   fprintf(stderr,"fxmesa: set_buffer(%d)\n",mode);
  316. #endif
  317.  
  318.   if (fxMesa->double_buffer) {
  319.     if(mode==GL_FRONT)
  320.       fxMesa->currentfb = GR_BUFFER_FRONTBUFFER;
  321.     else if(mode==GL_BACK)
  322.       fxMesa->currentfb = GR_BUFFER_BACKBUFFER;
  323.     else
  324.       return GL_FALSE;
  325.   } else {
  326.     if(mode==GL_FRONT)
  327.       fxMesa->currentfb = GR_BUFFER_FRONTBUFFER;
  328.     else
  329.       return GL_FALSE;
  330.   }
  331.  
  332.   grRenderBuffer(fxMesa->currentfb);
  333.   return GL_TRUE;
  334. }
  335.  
  336.  
  337. static GLboolean drawbitmap(GLcontext *ctx, GLsizei width, GLsizei height,
  338.                             GLfloat xorig, GLfloat yorig,
  339.                             GLfloat xmove, GLfloat ymove,
  340.                             const struct gl_image *bitmap)
  341. {
  342.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  343.   FxU16 *p;
  344.   GrLfbInfo_t info;
  345.   GLubyte *pb;
  346.   int x,y;
  347.   GLint r,g,b,a,px,py,scrwidth,scrheight,stride;
  348.   FxU16 color;
  349.  
  350. #define ISCLIPPED(rx) ( ((rx)<0) || ((rx)>=scrwidth) )
  351. #define DRAWBIT(i) {       \
  352.   if(!ISCLIPPED(x+px))       \
  353.     if( (*pb) & (1<<(i)) ) \
  354.       (*p)=color;       \
  355.   p++;                     \
  356.   x++;               \
  357.   if(x>=width) {           \
  358.     pb++;                  \
  359.     break;                 \
  360.   }                        \
  361. }
  362.  
  363.   scrwidth=fxMesa->width;
  364.   scrheight=fxMesa->height;
  365.  
  366.   px=(GLint)((ctx->Current.RasterPos[0]-xorig)+0.0F);
  367.   py=(GLint)((ctx->Current.RasterPos[1]-yorig)+0.0F);
  368.  
  369.   if((px>=scrwidth) || (px+width<=0) || (py>=scrheight) || (py+height<=0))
  370.     return GL_TRUE;
  371.  
  372.   pb=(GLubyte *)bitmap->Data;
  373.  
  374.   if(py<0) {
  375.     pb+=(bitmap->Height*(-py)) >> (3+1);
  376.     height+=py;
  377.     py=0;
  378.   }
  379.  
  380.   if(py+height>=scrheight)
  381.     height-=(py+height)-scrheight;
  382.  
  383.   info.size=sizeof(info);
  384.   if(!grLfbLock(GR_LFB_WRITE_ONLY,
  385.         fxMesa->currentfb,
  386.         GR_LFBWRITEMODE_565,
  387.         GR_ORIGIN_UPPER_LEFT,
  388.         FXFALSE,
  389.         &info)) {
  390. #ifndef FX_SILENT
  391.     fprintf(stderr,"fx Driver: error locking the linear frame buffer\n");
  392. #endif
  393.     return GL_TRUE;
  394.   }
  395.  
  396.   r=(GLint)(ctx->Current.RasterColor[0]*ctx->Visual->RedScale);
  397.   g=(GLint)(ctx->Current.RasterColor[1]*ctx->Visual->GreenScale);
  398.   b=(GLint)(ctx->Current.RasterColor[2]*ctx->Visual->BlueScale);
  399.   a=(GLint)(ctx->Current.RasterColor[3]*ctx->Visual->AlphaScale);
  400.   color=(FxU16)
  401.     ( ((FxU16)0xf8 & r) <<(11-3))  |
  402.     ( ((FxU16)0xfc & g) <<(5-3+1)) |
  403.     ( ((FxU16)0xf8 & b) >> 3);
  404.  
  405.   stride=info.strideInBytes>>1;
  406.  
  407.   /* This code is a bit slow... */
  408.  
  409.   for(y=0;y<height;y++) {
  410.     p=((FxU16 *)info.lfbPtr)+px+((scrheight-(y+py))*stride);
  411.  
  412.     for(x=0;;) {
  413.       DRAWBIT(7);    DRAWBIT(6);    DRAWBIT(5);    DRAWBIT(4);
  414.       DRAWBIT(3);    DRAWBIT(2);    DRAWBIT(1);    DRAWBIT(0);
  415.       pb++;
  416.     }
  417.   }
  418.  
  419.   grLfbUnlock(GR_LFB_WRITE_ONLY,fxMesa->currentfb);
  420.  
  421. #undef ISCLIPPED
  422. #undef DRAWBIT
  423.  
  424.   return GL_TRUE;
  425. }
  426.  
  427. /************************************************************************/
  428. /**************** 3D depth buffer functions *****************************/
  429. /************************************************************************/
  430.  
  431. /* this is a no-op, since the z-buffer is in hardware */
  432. static void alloc_depth_buffer(GLcontext *ctx)
  433. {
  434. #if defined(DEBUG_FXMESA)
  435.   fprintf(stderr,"fxmesa: alloc_depth_buffer()\n");
  436. #endif
  437. }
  438.  
  439. static void clear_depth_buffer(GLcontext *ctx)
  440. {
  441.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  442.  
  443. #if defined(DEBUG_FXMESA)
  444.   fprintf(stderr,"fxmesa: clear_depth_buffer()\n");
  445. #endif
  446.  
  447.   if(ctx->Depth.Test && ctx->Depth.Mask) {
  448.     grDepthMask(FXTRUE);
  449.     grColorMask(FXFALSE,FXFALSE);
  450.  
  451.     if(fxMesa->wbuffer)
  452.       /* I don't know how to convert ctx->Depth.Clear */
  453.       grBufferClear(fxMesa->clearc,fxMesa->cleara,GR_WDEPTHVALUE_FARTHEST);
  454.     else
  455.       grBufferClear(fxMesa->clearc,fxMesa->cleara,(FxU16)(ctx->Depth.Clear*0xffff));
  456.  
  457.     grColorMask(FXTRUE,FXFALSE);
  458.   }
  459. }
  460.  
  461. /************************************************************************/
  462. /*****                Span functions                                *****/
  463. /************************************************************************/
  464.  
  465. static void write_color_span( GLcontext *ctx, 
  466.                               GLuint n, GLint x, GLint y,
  467.                               const GLubyte red[], const GLubyte green[],
  468.                               const GLubyte blue[], const GLubyte alpha[],
  469.                               const GLubyte mask[] )
  470. {
  471.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  472.   GLubyte data[MAX_WIDTH][4];
  473.   GLint i;
  474.   GLint bottom = fxMesa->height-1;
  475.  
  476. #if defined(DEBUG_FXMESA)
  477.   fprintf(stderr,"fxmesa: write_color_span()\n");
  478. #endif
  479.  
  480.   grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
  481.  
  482.   if (mask) {
  483.     /* this is really inefficient, but it works */
  484.     for (i=0;i<n;i++) {
  485.       if (mask[i]) {
  486.         data[0][0] = red[i];
  487.         data[0][1] = green[i];
  488.         data[0][2] = blue[i];
  489.         data[0][3] = alpha[i];
  490.         grLfbWriteRegion( fxMesa->currentfb, x+i, bottom-y,
  491.                           GR_LFB_SRC_FMT_8888, 1, 1, 0, data );
  492.       }
  493.     }
  494.   }
  495.   else {
  496.     for (i=0;i<n;i++) {
  497.       data[i][0] = red[i];
  498.       data[i][1] = green[i];
  499.       data[i][2] = blue[i];
  500.       data[i][3] = alpha[i];
  501.     }
  502.     grLfbWriteRegion( fxMesa->currentfb, x, bottom-y, GR_LFB_SRC_FMT_8888,
  503.                       n, 1, 0, data );
  504.   }
  505. }
  506.  
  507.  
  508. static void write_monocolor_span( GLcontext *ctx, 
  509.                                   GLuint n, GLint x, GLint y,
  510.                                   const GLubyte mask[] )
  511. {
  512.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  513.   GLint i;
  514.   GLint bottom = fxMesa->height-1;
  515.  
  516. #if defined(DEBUG_FXMESA)
  517.   fprintf(stderr,"fxmesa: write_color_span()\n");
  518. #endif
  519.  
  520.   grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
  521.  
  522.   if (mask) {
  523.     /* this is really inefficient, but it works */
  524.     for (i=0;i<n;i++) {
  525.       if (mask[i]) {
  526.         grLfbWriteRegion( fxMesa->currentfb, x+i, bottom-y,
  527.                           GR_LFB_SRC_FMT_8888, 1, 1, 0,
  528.                           (GLubyte *) &fxMesa->color );
  529.       }
  530.     }
  531.   }
  532.   else {
  533.     GLuint data[MAX_WIDTH];
  534.     for (i=0;i<n;i++) {
  535.        data[i] = (GLuint) fxMesa->color;
  536.     }
  537.     grLfbWriteRegion( fxMesa->currentfb, x, bottom-y, GR_LFB_SRC_FMT_8888,
  538.                       n, 1, 0, (GLubyte *) data );
  539.   }
  540. }
  541.  
  542.  
  543. static void read_color_span( GLcontext *ctx, 
  544.                              GLuint n, GLint x, GLint y,
  545.                              GLubyte red[], GLubyte green[],
  546.                              GLubyte blue[], GLubyte alpha[] )
  547. {
  548.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  549.   GLushort data[MAX_WIDTH];
  550.   GLint i;
  551.   GLint bottom = fxMesa->height-1;
  552.  
  553. #if defined(DEBUG_FXMESA)
  554.   fprintf(stderr,"fxmesa: read_color_span()\n");
  555. #endif
  556.  
  557.   assert(n < MAX_WIDTH);
  558.   grLfbWriteColorFormat(GR_COLORFORMAT_RGBA);  /* controls reading too! */
  559.   grLfbReadRegion( fxMesa->currentfb, x, bottom-y, n, 1, 0, data);
  560.   for (i=0;i<n;i++) {
  561.     red[i]   = (data[i] & 0xf800) >> 8;
  562.     green[i] = (data[i] & 0x07e0) >> 3;
  563.     blue[i]  = (data[i] & 0x001f) << 3;
  564.     alpha[i] = 255;
  565.   }
  566. }
  567.  
  568. /************************************************************************/
  569. /************************************************************************/
  570. /************************************************************************/
  571.  
  572. static void finish(GLcontext *ctx)
  573. {
  574.   grSstIdle();
  575. }
  576.  
  577. static void flush(GLcontext *ctx)
  578. {
  579.   grSstIdle();
  580. }
  581.  
  582. /************************************************************************/
  583. /*************************** Texture Mapping ****************************/
  584. /************************************************************************/
  585.  
  586. static texinfo *alloctexobjdata(void)
  587. {
  588.   texinfo *ti;
  589.  
  590.   if(!(ti=malloc(sizeof(texinfo)))) {
  591.     fprintf(stderr,"fx Driver: out of memory !\n");
  592.     fxCloseHardware();
  593.     exit(-1);
  594.   }
  595.  
  596.   ti->valid=GL_FALSE;
  597.   ti->tmi.isintexturememory=GL_FALSE;
  598.  
  599.   return ti;
  600. }
  601.  
  602. static void texbind(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj)
  603. {
  604.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  605.   texinfo *ti;
  606.  
  607. #if defined(DEBUG_FXMESA)
  608.   fprintf(stderr,"fxmesa: texbind(%d,%x)\n",tObj->Name,tObj->DriverData);
  609. #endif
  610.  
  611.   if(target!=GL_TEXTURE_2D) {
  612. #ifndef FX_SILENT
  613.     fprintf(stderr,"fx Driver: unsupported texture in texbind()\n");
  614. #endif
  615.     return;
  616.   }
  617.  
  618.   if(!tObj->DriverData)
  619.     tObj->DriverData=alloctexobjdata();
  620.  
  621.   ti=(texinfo *)tObj->DriverData;
  622.  
  623.   if(!ti->valid)
  624.     return;
  625.  
  626.   fxMesa->texbindnumber++;
  627.   ti->tmi.lasttimeused=fxMesa->texbindnumber;
  628.  
  629.   moveintexturememory(fxMesa,tObj);
  630.  
  631.   if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->globalpalette_texture)) {
  632. #if defined(DEBUG_FXMESA)
  633.     fprintf(stderr,"fxmesa: uploading texture palette\n");
  634. #endif
  635.     grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette));
  636.   }
  637.  
  638.   grTexClampMode(GR_TMU0,ti->sclamp,ti->tclamp);
  639.   grTexFilterMode(GR_TMU0,ti->minfilt,ti->maxfilt);
  640.   grTexMipMapMode(GR_TMU0,ti->mmmode,FXFALSE);
  641.   grTexSource(GR_TMU0,ti->tmi.tm->startadr,GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
  642. }
  643.  
  644. static void texenv(GLcontext *ctx, GLenum pname, const GLfloat *param)
  645. {
  646.   /* ;) */
  647. }
  648.  
  649. static void texparam(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj,
  650.                      GLenum pname, const GLfloat *params)
  651. {
  652.   GLenum param=(GLenum)(GLint)params[0];
  653.   texinfo *ti;
  654.  
  655. #if defined(DEBUG_FXMESA)
  656.   fprintf(stderr,"fxmesa: texparam(%d,%x)\n",tObj->Name,tObj->DriverData);
  657. #endif
  658.  
  659.   if(target!=GL_TEXTURE_2D) {
  660. #ifndef FX_SILENT
  661.     fprintf(stderr,"fx Driver: unsupported texture in texparam()\n");
  662. #endif
  663.     return;
  664.   }
  665.  
  666.   if(!tObj->DriverData)
  667.     tObj->DriverData=alloctexobjdata();
  668.  
  669.   ti=(texinfo *)tObj->DriverData;
  670.  
  671.   switch(pname) {
  672.  
  673.   case GL_TEXTURE_MIN_FILTER:
  674.     switch(param) {
  675.     case GL_NEAREST:
  676.       ti->mmmode=GR_MIPMAP_DISABLE;
  677.       ti->minfilt=GR_TEXTUREFILTER_POINT_SAMPLED;
  678.       break;
  679.     case GL_LINEAR:
  680.       ti->mmmode=GR_MIPMAP_DISABLE;
  681.       ti->minfilt=GR_TEXTUREFILTER_BILINEAR;
  682.       break;
  683.     case GL_NEAREST_MIPMAP_NEAREST:
  684.       ti->mmmode=GR_MIPMAP_NEAREST;
  685.       ti->minfilt=GR_TEXTUREFILTER_POINT_SAMPLED;
  686.       break;
  687.     case GL_NEAREST_MIPMAP_LINEAR:
  688.       ti->mmmode=GR_MIPMAP_NEAREST;
  689.       ti->minfilt=GR_TEXTUREFILTER_BILINEAR;
  690.       break;
  691.     case GL_LINEAR_MIPMAP_LINEAR:
  692.       ti->mmmode=GR_MIPMAP_NEAREST_DITHER;
  693.       ti->minfilt=GR_TEXTUREFILTER_BILINEAR;
  694.       break;
  695.     default:
  696.       break;
  697.     }
  698.     break;
  699.  
  700.   case GL_TEXTURE_MAG_FILTER:
  701.     switch(param) {
  702.     case GL_NEAREST:
  703.       ti->maxfilt=GR_TEXTUREFILTER_POINT_SAMPLED;
  704.       break;
  705.     case GL_LINEAR:
  706.       ti->maxfilt=GR_TEXTUREFILTER_BILINEAR;
  707.       break;
  708.     default:
  709.       break;
  710.     }
  711.     break;
  712.  
  713.   case GL_TEXTURE_WRAP_S:
  714.     switch(param) {
  715.     case GL_CLAMP:
  716.       ti->sclamp=GR_TEXTURECLAMP_CLAMP;
  717.       break;
  718.     case GL_REPEAT:
  719.       ti->sclamp=GR_TEXTURECLAMP_WRAP;
  720.       break;
  721.     default:
  722.       break;
  723.     }
  724.     break;
  725.  
  726.   case GL_TEXTURE_WRAP_T:
  727.     switch(param) {
  728.     case GL_CLAMP:
  729.       ti->tclamp=GR_TEXTURECLAMP_CLAMP;
  730.       break;
  731.     case GL_REPEAT:
  732.       ti->tclamp=GR_TEXTURECLAMP_WRAP;
  733.       break;
  734.     default:
  735.       break;
  736.     }
  737.     break;
  738.  
  739.   case GL_TEXTURE_BORDER_COLOR:
  740.     /* TO DO */
  741.     break;
  742.   default:
  743.     break;
  744.   }
  745.  
  746.   texbind(ctx,target,tObj);
  747. }
  748.  
  749. static void texdel(GLcontext *ctx, struct gl_texture_object *tObj)
  750. {
  751.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  752.   texinfo *ti=(texinfo *)tObj->DriverData;
  753.  
  754. #if defined(DEBUG_FXMESA)
  755.   fprintf(stderr,"fxmesa: texdel(%d,%x)\n",tObj->Name,ti);
  756. #endif
  757.  
  758.   if(!ti)
  759.     return;
  760.  
  761.   freetexture(fxMesa,tObj);
  762.  
  763.   free(ti);
  764.   tObj->DriverData=NULL;
  765. }
  766.  
  767.  
  768. static void texpalette(GLcontext *ctx, struct gl_texture_object *tObj)
  769. {
  770.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  771.   int i;
  772.   FxU32 r,g,b,a;
  773.   texinfo *ti;
  774.  
  775.   if(tObj) {  
  776. #if defined(DEBUG_FXMESA)
  777.     fprintf(stderr,"fxmesa: texpalette(%d,%x)\n",tObj->Name,tObj->DriverData);
  778. #endif
  779.  
  780.     if(tObj->PaletteFormat!=GL_RGBA) {
  781. #ifndef FX_SILENT
  782.       fprintf(stderr,"fxmesa: unsupported palette format in texpalette()\n");
  783. #endif
  784.       return;
  785.     }
  786.  
  787.     if(tObj->PaletteSize>256) {
  788. #ifndef FX_SILENT
  789.       fprintf(stderr,"fxmesa: unsupported palette size in texpalette()\n");
  790. #endif
  791.       return;
  792.     }
  793.  
  794.     if(!tObj->DriverData)
  795.       tObj->DriverData=alloctexobjdata();
  796.   
  797.     ti=(texinfo *)tObj->DriverData;
  798.  
  799.     for(i=0;i<tObj->PaletteSize;i++) {
  800.       r=tObj->Palette[i*4];
  801.       g=tObj->Palette[i*4+1];
  802.       b=tObj->Palette[i*4+2];
  803.       a=tObj->Palette[i*4+3];
  804.       ti->palette.data[i]=(a<<24)|(r<<16)|(g<<8)|b;
  805.     }
  806.   
  807.     texbind(ctx,GL_TEXTURE_2D,tObj);
  808.   } else {
  809. #if defined(DEBUG_FXMESA)
  810.     fprintf(stderr,"fxmesa: texpalette(global)\n");
  811. #endif
  812.     if(ctx->Texture.PaletteFormat!=GL_RGBA) {
  813. #ifndef FX_SILENT
  814.       fprintf(stderr,"fxmesa: unsupported palette format in texpalette()\n");
  815. #endif
  816.       return;
  817.     }
  818.  
  819.     if(ctx->Texture.PaletteSize>256) {
  820. #ifndef FX_SILENT
  821.       fprintf(stderr,"fxmesa: unsupported palette size in texpalette()\n");
  822. #endif
  823.       return;
  824.     }
  825.  
  826.     for(i=0;i<ctx->Texture.PaletteSize;i++) {
  827.       r=ctx->Texture.Palette[i*4];
  828.       g=ctx->Texture.Palette[i*4+1];
  829.       b=ctx->Texture.Palette[i*4+2];
  830.       a=ctx->Texture.Palette[i*4+3];
  831.       fxMesa->glbpalette.data[i]=(a<<24)|(r<<16)|(g<<8)|b;
  832.     }
  833.  
  834.     grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(fxMesa->glbpalette));
  835.   }
  836. }
  837.  
  838. static void useglbtexpalette(GLcontext *ctx, GLboolean state)
  839. {
  840.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  841.  
  842. #if defined(DEBUG_FXMESA)
  843.   fprintf(stderr,"fxmesa: useglbtexpalette(%d)\n",state);
  844. #endif
  845.  
  846.   if(state) {
  847.     fxMesa->globalpalette_texture=1;
  848.  
  849.     grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(fxMesa->glbpalette));
  850.   } else {
  851.     fxMesa->globalpalette_texture=0;
  852.  
  853.     if((ctx->Texture.Current==ctx->Texture.Current2D) &&
  854.        (ctx->Texture.Current2D!=NULL))
  855.       texbind(ctx,GL_TEXTURE_2D,ctx->Texture.Current);
  856.   }
  857. }
  858.  
  859. static int logbase2(int n)
  860. {
  861.   GLint i = 1;
  862.   GLint log2 = 0;
  863.  
  864.   if (n<0) {
  865.     return -1;
  866.   }
  867.  
  868.   while (n > i) {
  869.     i *= 2;
  870.     log2++;
  871.   }
  872.   if (i != n) {
  873.     return -1;
  874.   }
  875.   else {
  876.     return log2;
  877.   }
  878. }
  879.  
  880. int texgetinfo(int w, int h, GrLOD_t *lodlevel, GrAspectRatio_t *ar,
  881.            float *sscale, float *tscale,
  882.            int *wscale, int *hscale)
  883. {
  884.   static GrLOD_t lod[9]={GR_LOD_256,GR_LOD_128,GR_LOD_64,GR_LOD_32,
  885.                          GR_LOD_16,GR_LOD_8,GR_LOD_4,GR_LOD_2,GR_LOD_1};
  886.   int logw,logh,ws,hs;
  887.   GrLOD_t l;
  888.   GrAspectRatio_t aspectratio;
  889.   float s,t;
  890.  
  891.   logw=logbase2(w);
  892.   logh=logbase2(h);
  893.  
  894.   switch(logw-logh) {
  895.   case 0:
  896.     aspectratio=GR_ASPECT_1x1;
  897.     l=lod[8-logw];
  898.     s=t=256.0f;
  899.     ws=hs=1;
  900.     break;
  901.   case 1:
  902.     aspectratio=GR_ASPECT_2x1;
  903.     l=lod[8-logw];
  904.     s=256.0f;
  905.     t=128.0f;
  906.     ws=1;
  907.     hs=1;
  908.     break;
  909.   case 2:
  910.     aspectratio=GR_ASPECT_4x1;
  911.     l=lod[8-logw];
  912.     s=256.0f;
  913.     t=64.0f;
  914.     ws=1;
  915.     hs=1;
  916.     break;
  917.   case 3:
  918.     aspectratio=GR_ASPECT_8x1;
  919.     l=lod[8-logw];
  920.     s=256.0f;
  921.     t=32.0f;
  922.     ws=1;
  923.     hs=1;
  924.     break;
  925.   case 4:
  926.     aspectratio=GR_ASPECT_8x1;
  927.     l=lod[8-logw];
  928.     s=256.0f;
  929.     t=32.0f;
  930.     ws=1;
  931.     hs=2;
  932.     break;
  933.   case 5:
  934.     aspectratio=GR_ASPECT_8x1;
  935.     l=lod[8-logw];
  936.     s=256.0f;
  937.     t=32.0f;
  938.     ws=1;
  939.     hs=4;
  940.     break;
  941.   case 6:
  942.     aspectratio=GR_ASPECT_8x1;
  943.     l=lod[8-logw];
  944.     s=256.0f;
  945.     t=32.0f;
  946.     ws=1;
  947.     hs=8;
  948.     break;
  949.   case 7:
  950.     aspectratio=GR_ASPECT_8x1;
  951.     l=lod[8-logw];
  952.     s=256.0f;
  953.     t=32.0f;
  954.     ws=1;
  955.     hs=16;
  956.     break;
  957.   case 8:
  958.     aspectratio=GR_ASPECT_8x1;
  959.     l=lod[8-logw];
  960.     s=256.0f;
  961.     t=32.0f;
  962.     ws=1;
  963.     hs=32;
  964.     break;
  965.   case -1:
  966.     aspectratio=GR_ASPECT_1x2;
  967.     l=lod[8-logh];
  968.     s=128.0f;
  969.     t=256.0f;
  970.     ws=1;
  971.     hs=1;
  972.     break;
  973.   case -2:
  974.     aspectratio=GR_ASPECT_1x4;
  975.     l=lod[8-logh];
  976.     s=64.0f;
  977.     t=256.0f;
  978.     ws=1;
  979.     hs=1;
  980.     break;
  981.   case -3:
  982.     aspectratio=GR_ASPECT_1x8;
  983.     l=lod[8-logh];
  984.     s=32.0f;
  985.     t=256.0f;
  986.     ws=1;
  987.     hs=1;
  988.     break;
  989.   case -4:
  990.     aspectratio=GR_ASPECT_1x8;
  991.     l=lod[8-logh];
  992.     s=32.0f;
  993.     t=256.0f;
  994.     ws=2;
  995.     hs=1;
  996.     break;
  997.   case -5:
  998.     aspectratio=GR_ASPECT_1x8;
  999.     l=lod[8-logh];
  1000.     s=32.0f;
  1001.     t=256.0f;
  1002.     ws=4;
  1003.     hs=1;
  1004.     break;
  1005.   case -6:
  1006.     aspectratio=GR_ASPECT_1x8;
  1007.     l=lod[8-logh];
  1008.     s=32.0f;
  1009.     t=256.0f;
  1010.     ws=8;
  1011.     hs=1;
  1012.     break;
  1013.   case -7:
  1014.     aspectratio=GR_ASPECT_1x8;
  1015.     l=lod[8-logh];
  1016.     s=32.0f;
  1017.     t=256.0f;
  1018.     ws=16;
  1019.     hs=1;
  1020.     break;
  1021.   case -8:
  1022.     aspectratio=GR_ASPECT_1x8;
  1023.     l=lod[8-logh];
  1024.     s=32.0f;
  1025.     t=256.0f;
  1026.     ws=32;
  1027.     hs=1;
  1028.     break;
  1029.   default:
  1030.     return 0;
  1031.     break;
  1032.   }
  1033.  
  1034.   if(lodlevel)
  1035.     (*lodlevel)=l;
  1036.  
  1037.   if(ar)
  1038.     (*ar)=aspectratio;
  1039.  
  1040.   if(sscale)
  1041.     (*sscale)=s;
  1042.  
  1043.   if(tscale)
  1044.     (*tscale)=t;
  1045.  
  1046.   if(wscale)
  1047.     (*wscale)=ws;
  1048.  
  1049.   if(hscale)
  1050.     (*hscale)=hs;
  1051.  
  1052.   return 1;
  1053. }
  1054.  
  1055. static GrTextureFormat_t texgetformat(GLcontext *ctx, GLenum glformat)
  1056. {
  1057.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  1058.   GrTextureFormat_t format;
  1059.  
  1060.   switch(glformat) {
  1061.   case GL_INTENSITY:
  1062.   case GL_INTENSITY4:
  1063.   case GL_INTENSITY8:
  1064.   case GL_INTENSITY12:
  1065.   case GL_INTENSITY16:
  1066.     /* TO DO: check */
  1067.   case 1:
  1068.   case GL_LUMINANCE:
  1069.   case GL_LUMINANCE4:
  1070.   case GL_LUMINANCE8:
  1071.   case GL_LUMINANCE12:
  1072.   case GL_LUMINANCE16:
  1073.     format=GR_TEXFMT_INTENSITY_8;
  1074.     break;
  1075.   case 2:
  1076.   case GL_LUMINANCE_ALPHA:
  1077.   case GL_LUMINANCE4_ALPHA4:
  1078.   case GL_LUMINANCE6_ALPHA2:
  1079.   case GL_LUMINANCE8_ALPHA8:
  1080.   case GL_LUMINANCE12_ALPHA4:
  1081.   case GL_LUMINANCE12_ALPHA12:
  1082.   case GL_LUMINANCE16_ALPHA16:
  1083.     format=GR_TEXFMT_ALPHA_INTENSITY_88;
  1084.     break;
  1085.   case GL_ALPHA:
  1086.   case GL_ALPHA4:
  1087.   case GL_ALPHA8:
  1088.   case GL_ALPHA12:
  1089.   case GL_ALPHA16:
  1090.     format=GR_TEXFMT_ALPHA_8;
  1091.     break;
  1092.   case 3:
  1093.   case GL_RGB:
  1094.   case GL_R3_G3_B2:
  1095.   case GL_RGB4:
  1096.   case GL_RGB5:
  1097.   case GL_RGB8:
  1098.   case GL_RGB10:
  1099.   case GL_RGB12:
  1100.   case GL_RGB16:
  1101.     if(fxMesa->fixedpalette_texture)
  1102.       format=GR_TEXFMT_P_8;
  1103.     else
  1104.       format=GR_TEXFMT_RGB_565;
  1105.     break;
  1106.   case 4:
  1107.   case GL_RGBA:
  1108.   case GL_RGBA2:
  1109.   case GL_RGBA4:
  1110.   case GL_RGB5_A1:
  1111.   case GL_RGBA8:
  1112.   case GL_RGB10_A2:
  1113.   case GL_RGBA12:
  1114.   case GL_RGBA16:
  1115.     format=GR_TEXFMT_ARGB_4444;
  1116.     break;
  1117.   case GL_COLOR_INDEX:
  1118.   case GL_COLOR_INDEX1_EXT:
  1119.   case GL_COLOR_INDEX2_EXT:
  1120.   case GL_COLOR_INDEX4_EXT:
  1121.   case GL_COLOR_INDEX8_EXT:
  1122.   case GL_COLOR_INDEX12_EXT:
  1123.   case GL_COLOR_INDEX16_EXT:
  1124.     format=GR_TEXFMT_P_8;
  1125.     break;
  1126.   default:
  1127.     fprintf(stderr,"fx Driver: unsupported internalFormat in texgetformat()\n");
  1128.     fxCloseHardware();
  1129.     exit(-1);
  1130.     break;
  1131.   }
  1132.  
  1133.   return format;
  1134. }
  1135.  
  1136. static void texalloc(GLcontext *ctx, struct gl_texture_object *tObj,
  1137.              GLenum glformat, int w, int h)
  1138. {
  1139.   GrTextureFormat_t format;
  1140.   GrLOD_t l;
  1141.   GrAspectRatio_t aspectratio;
  1142.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  1143.   texinfo *ti=(texinfo *)tObj->DriverData;
  1144.   int wscale,hscale;
  1145.  
  1146.   assert(ti);
  1147.  
  1148.   texgetinfo(w,h,&l,&aspectratio,&(ti->sscale),&(ti->tscale),&wscale,&hscale);
  1149.  
  1150.   format=texgetformat(ctx,glformat);
  1151.  
  1152.   ti->width=w;
  1153.   ti->height=h;
  1154.   ti->info.smallLod=l;
  1155.   ti->info.largeLod=l;
  1156.   ti->info.aspectRatio=aspectratio;
  1157.   ti->info.format=format;
  1158.   ti->info.data=NULL;
  1159.  
  1160.   ti->fixedpalette=fxMesa->fixedpalette_texture;
  1161.  
  1162.   ti->minfilt=GR_TEXTUREFILTER_BILINEAR;
  1163.   ti->maxfilt=GR_TEXTUREFILTER_BILINEAR;
  1164.  
  1165.   ti->sclamp=GR_TEXTURECLAMP_WRAP;
  1166.   ti->tclamp=GR_TEXTURECLAMP_WRAP;
  1167.  
  1168.   ti->mmmode=GR_MIPMAP_NEAREST;
  1169.  
  1170.   ti->levelsdefined=0;
  1171. }
  1172.  
  1173. static int istexsupported(GLenum target, GLint internalFormat,
  1174.                           const struct gl_texture_image *image)
  1175. {
  1176.   if(target!=GL_TEXTURE_2D)
  1177.     return GL_FALSE;
  1178.  
  1179.   switch(internalFormat) {
  1180.   case GL_INTENSITY:
  1181.   case GL_INTENSITY4:
  1182.   case GL_INTENSITY8:
  1183.   case GL_INTENSITY12:
  1184.   case GL_INTENSITY16:
  1185.   case 1:
  1186.   case GL_LUMINANCE:
  1187.   case GL_LUMINANCE4:
  1188.   case GL_LUMINANCE8:
  1189.   case GL_LUMINANCE12:
  1190.   case GL_LUMINANCE16:
  1191.   case 2:
  1192.   case GL_LUMINANCE_ALPHA:
  1193.   case GL_LUMINANCE4_ALPHA4:
  1194.   case GL_LUMINANCE6_ALPHA2:
  1195.   case GL_LUMINANCE8_ALPHA8:
  1196.   case GL_LUMINANCE12_ALPHA4:
  1197.   case GL_LUMINANCE12_ALPHA12:
  1198.   case GL_LUMINANCE16_ALPHA16:
  1199.   case GL_ALPHA:
  1200.   case GL_ALPHA4:
  1201.   case GL_ALPHA8:
  1202.   case GL_ALPHA12:
  1203.   case GL_ALPHA16:
  1204.   case 3:
  1205.   case GL_RGB:
  1206.   case GL_R3_G3_B2:
  1207.   case GL_RGB4:
  1208.   case GL_RGB5:
  1209.   case GL_RGB8:
  1210.   case GL_RGB10:
  1211.   case GL_RGB12:
  1212.   case GL_RGB16:
  1213.   case 4:
  1214.   case GL_RGBA:
  1215.   case GL_RGBA2:
  1216.   case GL_RGBA4:
  1217.   case GL_RGB5_A1:
  1218.   case GL_RGBA8:
  1219.   case GL_RGB10_A2:
  1220.   case GL_RGBA12:
  1221.   case GL_RGBA16:
  1222.   case GL_COLOR_INDEX:
  1223.   case GL_COLOR_INDEX1_EXT:
  1224.   case GL_COLOR_INDEX2_EXT:
  1225.   case GL_COLOR_INDEX4_EXT:
  1226.   case GL_COLOR_INDEX8_EXT:
  1227.   case GL_COLOR_INDEX12_EXT:
  1228.   case GL_COLOR_INDEX16_EXT:
  1229.     break;
  1230.   default:
  1231.     return GL_FALSE;
  1232.   }
  1233.  
  1234.   if(image->Width>256)
  1235.     return GL_FALSE;
  1236.  
  1237.   if(image->Height>256)
  1238.     return GL_FALSE;
  1239.  
  1240.   if(!texgetinfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL))
  1241.     return GL_FALSE;
  1242.  
  1243.   return GL_TRUE;
  1244. }
  1245.  
  1246. static void texbuildimagemap(const struct gl_texture_image *image,
  1247.                  GLint internalFormat, GuTexPalette *palette,
  1248.                  GLint levelsdefined, unsigned short **newsrc)
  1249. {
  1250.   unsigned short *src,*srccpy;
  1251.   unsigned char r,g,b,a,l,*data,*srcb;
  1252.   int x,y,w,h,wscale,hscale,idx;
  1253.  
  1254.   texgetinfo(image->Width,image->Height,NULL,NULL,NULL,NULL,&wscale,&hscale);
  1255.   w=image->Width*wscale;
  1256.   h=image->Height*hscale;
  1257.  
  1258.   data=image->Data;
  1259.   switch(internalFormat) {
  1260.   case GL_INTENSITY:
  1261.   case GL_INTENSITY4:
  1262.   case GL_INTENSITY8:
  1263.   case GL_INTENSITY12:
  1264.   case GL_INTENSITY16:
  1265.   case 1:
  1266.   case GL_LUMINANCE:
  1267.   case GL_LUMINANCE4:
  1268.   case GL_LUMINANCE8:
  1269.   case GL_LUMINANCE12:
  1270.   case GL_LUMINANCE16:
  1271.   case GL_ALPHA:
  1272.   case GL_ALPHA4:
  1273.   case GL_ALPHA8:
  1274.   case GL_ALPHA12:
  1275.   case GL_ALPHA16:
  1276.   case GL_COLOR_INDEX:
  1277.   case GL_COLOR_INDEX1_EXT:
  1278.   case GL_COLOR_INDEX2_EXT:
  1279.   case GL_COLOR_INDEX4_EXT:
  1280.   case GL_COLOR_INDEX8_EXT:
  1281.   case GL_COLOR_INDEX12_EXT:
  1282.   case GL_COLOR_INDEX16_EXT:
  1283.     if(!(*newsrc)) {
  1284.       if(!((*newsrc)=srccpy=src=(unsigned short *)malloc(sizeof(unsigned char)*w*h))) {
  1285.         fprintf(stderr,"fx Driver: out of memory !\n");
  1286.         fxCloseHardware();
  1287.         exit(-1);
  1288.       }
  1289.     } else
  1290.       srccpy=src=(*newsrc);
  1291.  
  1292.     /* Optimized for GLQuake */
  1293.  
  1294.     if(wscale==hscale==1)
  1295.       memcpy(src,data,h*w);
  1296.     else {
  1297.       srcb=(unsigned char *)src;
  1298.       for(y=0;y<h;y++)
  1299.         for(x=0;x<w;x++) {
  1300.           idx=(x/wscale+(y/hscale)*(w/wscale));
  1301.           srcb[x+y*w]=data[idx];
  1302.         }
  1303.     }
  1304.     break;
  1305.   case 2:
  1306.   case GL_LUMINANCE_ALPHA:
  1307.   case GL_LUMINANCE4_ALPHA4:
  1308.   case GL_LUMINANCE6_ALPHA2:
  1309.   case GL_LUMINANCE8_ALPHA8:
  1310.   case GL_LUMINANCE12_ALPHA4:
  1311.   case GL_LUMINANCE12_ALPHA12:
  1312.   case GL_LUMINANCE16_ALPHA16:
  1313.     if(!(*newsrc)) {
  1314.       if(!((*newsrc)=srccpy=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
  1315.         fprintf(stderr,"fx Driver: out of memory !\n");
  1316.         fxCloseHardware();
  1317.         exit(-1);
  1318.       }
  1319.     } else
  1320.       srccpy=src=(*newsrc);
  1321.  
  1322.  
  1323.     for(y=0;y<h;y++)
  1324.       for(x=0;x<w;x++) {
  1325.         idx=(x/wscale+(y/hscale)*(w/wscale))*2;
  1326.         l=data[idx];
  1327.         a=data[idx+1];
  1328.  
  1329.         src[x+y*w]=(unsigned short)
  1330.           (((unsigned short) a) << 8) |
  1331.           (((unsigned short) l));
  1332.       }
  1333.     break;
  1334.   case 3:
  1335.   case GL_RGB:
  1336.   case GL_R3_G3_B2:
  1337.   case GL_RGB4:
  1338.   case GL_RGB5:
  1339.   case GL_RGB8:
  1340.   case GL_RGB10:
  1341.   case GL_RGB12:
  1342.   case GL_RGB16:
  1343.     if(!(*newsrc)) {
  1344.       if(!((*newsrc)=srccpy=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
  1345.         fprintf(stderr,"fx Driver: out of memory !\n");
  1346.         fxCloseHardware();
  1347.         exit(-1);
  1348.       }
  1349.     } else
  1350.       srccpy=src=(*newsrc);
  1351.  
  1352.     if(palette) {
  1353.       Gu3dfInfo info;
  1354.       int memreq;
  1355.       unsigned char *expdata;
  1356.  
  1357.       if(!(expdata=malloc(w*h*3))) {
  1358.         fprintf(stderr,"fx Driver: out of memory\n");
  1359.         fxCloseHardware();
  1360.         exit(-1);
  1361.       }
  1362.  
  1363.       for(y=0;y<h;y++)
  1364.         for(x=0;x<w;x++) {
  1365.           idx=(x/wscale+(y/hscale)*(w/wscale))*3;
  1366.           r=data[idx];
  1367.           g=data[idx+1];
  1368.           b=data[idx+2];
  1369.  
  1370.           expdata[(x+y*w)*3]=r;
  1371.           expdata[(x+y*w)*3+1]=g;
  1372.           expdata[(x+y*w)*3+2]=b;
  1373.         }
  1374.  
  1375.       memreq=txInit3dfInfo(&info,GR_TEXFMT_P_8,&w,&h,1,TX_AUTORESIZE_DISABLE);
  1376.  
  1377.       if(!(info.data=malloc(memreq))) {
  1378.         fprintf(stderr,"fx Driver: out of memory\n");
  1379.         fxCloseHardware();
  1380.         exit(-1);
  1381.       }
  1382.  
  1383.       if(!levelsdefined) {
  1384.         txConvert(&info,GR_TEXFMT_RGB_888,w,h,expdata,TX_DITHER_ERR,NULL);
  1385.         memcpy(palette,&info.table.palette,sizeof(GuTexPalette));
  1386.       } else
  1387.         txConvert(&info,GR_TEXFMT_RGB_888,w,h,expdata,TX_TARGET_PALNCC_SOURCE|
  1388.           TX_DITHER_ERR,palette);
  1389.  
  1390.       memcpy(src,info.data,memreq);
  1391.  
  1392.       free(info.data);
  1393.       free(expdata);
  1394.     } else {
  1395.       for(y=0;y<h;y++)
  1396.         for(x=0;x<w;x++) {
  1397.           idx=(x/wscale+(y/hscale)*(w/wscale))*3;
  1398.           r=data[idx];
  1399.           g=data[idx+1];
  1400.           b=data[idx+2];
  1401.  
  1402.           src[x+y*w]=(unsigned short)
  1403.             (((unsigned short)0xf8 & r) <<(11-3))  |
  1404.             (((unsigned short)0xfc & g) <<(5-3+1)) |
  1405.             (((unsigned short)0xf8 & b) >> 3); 
  1406.         }
  1407.     }
  1408.     break;
  1409.   case 4:
  1410.   case GL_RGBA:
  1411.   case GL_RGBA2:
  1412.   case GL_RGBA4:
  1413.   case GL_RGB5_A1:
  1414.   case GL_RGBA8:
  1415.   case GL_RGB10_A2:
  1416.   case GL_RGBA12:
  1417.   case GL_RGBA16:
  1418.     if(!(*newsrc)) {
  1419.       if(!((*newsrc)=srccpy=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
  1420.         fprintf(stderr,"fx Driver: out of memory !\n");
  1421.         fxCloseHardware();
  1422.         exit(-1);
  1423.       }
  1424.     } else
  1425.       srccpy=src=(*newsrc);
  1426.  
  1427.     for(y=0;y<h;y++)
  1428.       for(x=0;x<w;x++) {
  1429.         idx=(x/wscale+(y/hscale)*(w/wscale))*4;
  1430.         r=data[idx];
  1431.         g=data[idx+1];
  1432.         b=data[idx+2];
  1433.         a=data[idx+3];
  1434.  
  1435.         src[x+y*w]=(unsigned short)
  1436.           (((unsigned short)0xf0 & a) << 8) |
  1437.           (((unsigned short)0xf0 & r) << 4) |
  1438.           ((unsigned short)0xf0 & g)       |
  1439.           (((unsigned short)0xf0 & b) >> 4); 
  1440.       }
  1441.     break;
  1442.   default:
  1443.     fprintf(stderr,"fx Driver: wrong internalFormat in texbuildimagemap()\n");
  1444.     fxCloseHardware();
  1445.     exit(-1);
  1446.     break;
  1447.   }
  1448. }
  1449.  
  1450. static void teximg(GLcontext *ctx, GLenum target,
  1451.                    struct gl_texture_object *tObj, GLint level, GLint internalFormat,
  1452.                    const struct gl_texture_image *image)
  1453. {
  1454.   GrLOD_t lodlev;
  1455.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  1456.   texinfo *ti;
  1457.  
  1458. #if defined(DEBUG_FXMESA)
  1459.   fprintf(stderr,"fxmesa: teximg(...,%d,%d,%d,%d...)\n",target,internalFormat,image->Width,image->Height);
  1460. #endif
  1461.  
  1462.   if(target!=GL_TEXTURE_2D) {
  1463. #ifndef FX_SILENT
  1464.     fprintf(stderr,"fx Driver: unsupported texture in teximg()\n");
  1465. #endif
  1466.     return;
  1467.   }
  1468.  
  1469.   if(!tObj->DriverData)
  1470.     tObj->DriverData=alloctexobjdata();
  1471.  
  1472.   ti=(texinfo *)tObj->DriverData;
  1473.  
  1474.   if(istexsupported(target,internalFormat,image)) {
  1475.     /* The following line isn't really right ... */
  1476.  
  1477.     if((!ti->valid) || (ti->info.format!=texgetformat(ctx,internalFormat)))
  1478.       texalloc(ctx,tObj,image->Format,image->Width,image->Height);
  1479.  
  1480.     if(ti->levelsdefined & (1<<level)) {
  1481.       if(ti->fixedpalette)
  1482.         texbuildimagemap(image,internalFormat,&ti->palette,
  1483.                      ti->levelsdefined,&(ti->tmi.mipmaplevel[level]));
  1484.       else
  1485.         texbuildimagemap(image,internalFormat,NULL,0,&(ti->tmi.mipmaplevel[level]));
  1486.  
  1487.       reloadmipmaplevel(fxMesa,tObj,level);
  1488.     } else {
  1489.       moveouttexturememory(fxMesa,tObj); /* TO DO: SLOW but easy to write */
  1490.  
  1491.       ti->tmi.mipmaplevel[level]=NULL;
  1492.  
  1493.       if(ti->fixedpalette)
  1494.         texbuildimagemap(image,internalFormat,&ti->palette,
  1495.                      ti->levelsdefined,&(ti->tmi.mipmaplevel[level]));
  1496.       else
  1497.         texbuildimagemap(image,internalFormat,NULL,0,&(ti->tmi.mipmaplevel[level]));
  1498.  
  1499.       texgetinfo(image->Width,image->Height,&lodlev,NULL,NULL,NULL,NULL,NULL);
  1500.  
  1501.       if(lodlev<ti->info.largeLod) /* A new larger mip map level */
  1502.         ti->info.largeLod=lodlev;
  1503.       else if(lodlev>ti->info.smallLod) /* A new smaller mip map level */
  1504.         ti->info.smallLod=lodlev;
  1505.  
  1506.       ti->levelsdefined|=(1<<level);
  1507.       ti->valid=GL_TRUE;
  1508.  
  1509.       texbind(ctx,target,tObj);
  1510.     }
  1511.   }
  1512. #ifndef FX_SILENT
  1513.   else
  1514.     fprintf(stderr,"fx Driver: unsupported texture in teximg()\n");
  1515. #endif
  1516. }
  1517.  
  1518. /************************************************************************/
  1519. /************************************************************************/
  1520. /************************************************************************/
  1521.  
  1522. static void SetNearFar(GLcontext *ctx, GLfloat n, GLfloat f)
  1523. {
  1524.   fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
  1525.  
  1526.   if(fxMesa) {
  1527.     fxMesa->nearval=fabs(n);
  1528.     fxMesa->farval=fabs(f);
  1529.     fxMesa->wscale=fxMesa->farval/65535.0;
  1530.  
  1531.     /*
  1532.      * We need to update fog table because it depends on w 
  1533.      * and w is adjusted to the maximum range.
  1534.      */
  1535.     if(ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST) {
  1536.       switch(ctx->Fog.Mode)     {
  1537.       case GL_LINEAR:
  1538.         guFogGenerateLinear(fxMesa->fogtable,
  1539.                             ctx->Fog.Start/fxMesa->wscale,
  1540.                             ctx->Fog.End /fxMesa->wscale); /* works ? */
  1541.         break;
  1542.       case GL_EXP:
  1543.         guFogGenerateExp(fxMesa->fogtable,
  1544.                          ctx->Fog.Density*fxMesa->wscale);
  1545.         break;
  1546.       case GL_EXP2:
  1547.         guFogGenerateExp2(fxMesa->fogtable,
  1548.                           ctx->Fog.Density*fxMesa->wscale);
  1549.         break;
  1550.       default: /* That should never happen */
  1551.         break; 
  1552.       }
  1553.     }
  1554.   }
  1555. }
  1556.  
  1557. void fxMesaSetNearFar(GLfloat n, GLfloat f)
  1558. {
  1559.   if(CurrentfxMesaCtx)
  1560.     SetNearFar(CurrentfxMesaCtx->gl_ctx, n, f);
  1561. }
  1562.  
  1563.  
  1564. static void setup_fx_units(GLcontext *ctx)
  1565. {
  1566.   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
  1567.  
  1568.   if(ctx->Color.BlendEnabled) {
  1569.     GrAlphaBlendFnc_t sfact,dfact;
  1570.  
  1571.     if(ctx->Light.ShadeModel==GL_SMOOTH)
  1572.       guAlphaSource(GR_ALPHASOURCE_ITERATED_ALPHA);
  1573.     else
  1574.       guAlphaSource(GR_ALPHASOURCE_CC_ALPHA);
  1575.  
  1576.     switch(ctx->Color.BlendSrc) {
  1577.     case GL_ZERO:
  1578.       sfact=GR_BLEND_ZERO;
  1579.       break;
  1580.     case GL_ONE:
  1581.       sfact=GR_BLEND_ONE;
  1582.       break;
  1583.     case GL_DST_COLOR:
  1584.       sfact=GR_BLEND_DST_COLOR;
  1585.       break;
  1586.     case GL_ONE_MINUS_DST_COLOR:
  1587.       sfact=GR_BLEND_ONE_MINUS_DST_COLOR;
  1588.       break;
  1589.     case GL_SRC_ALPHA:
  1590.       sfact=GR_BLEND_SRC_ALPHA;
  1591.       break;
  1592.     case GL_ONE_MINUS_SRC_ALPHA:
  1593.       sfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
  1594.       break;
  1595.     case GL_SRC_ALPHA_SATURATE:
  1596.     case GL_SRC_COLOR:
  1597.     case GL_ONE_MINUS_SRC_COLOR:
  1598.     case GL_DST_ALPHA:
  1599.     case GL_ONE_MINUS_DST_ALPHA:
  1600.       /* USELESS or TO DO */
  1601.       sfact=GR_BLEND_ONE;
  1602.       break;
  1603.     default:
  1604.       break;
  1605.     }
  1606.  
  1607.     switch(ctx->Color.BlendDst) {
  1608.     case GL_ZERO:
  1609.       dfact=GR_BLEND_ZERO;
  1610.       break;
  1611.     case GL_ONE:
  1612.       dfact=GR_BLEND_ONE;
  1613.       break;
  1614.     case GL_SRC_COLOR:
  1615.       dfact=GR_BLEND_SRC_COLOR;
  1616.       break;
  1617.     case GL_ONE_MINUS_SRC_COLOR:
  1618.       dfact=GR_BLEND_ONE_MINUS_SRC_COLOR;
  1619.       break;
  1620.     case GL_SRC_ALPHA:
  1621.       dfact=GR_BLEND_SRC_ALPHA;
  1622.       break;
  1623.     case GL_ONE_MINUS_SRC_ALPHA:
  1624.       dfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
  1625.       break;
  1626.     case GL_SRC_ALPHA_SATURATE:
  1627.     case GL_DST_COLOR:
  1628.     case GL_ONE_MINUS_DST_COLOR:
  1629.     case GL_DST_ALPHA:
  1630.     case GL_ONE_MINUS_DST_ALPHA:
  1631.       /* USELESS or TO DO */
  1632.       sfact=GR_BLEND_ZERO;
  1633.       break;
  1634.     default:
  1635.       break;
  1636.     }
  1637.  
  1638.     grAlphaBlendFunction(sfact,dfact,GR_BLEND_ONE,GR_BLEND_ZERO);
  1639.  
  1640.     grColorMask(FXTRUE,FXFALSE);
  1641.   } else {
  1642.     if(ctx->Light.ShadeModel==GL_SMOOTH)
  1643.       guAlphaSource(GR_ALPHASOURCE_ITERATED_ALPHA);
  1644.     else
  1645.       guAlphaSource(GR_ALPHASOURCE_CC_ALPHA);
  1646.  
  1647.     grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO);
  1648.     grColorMask(FXTRUE,FXFALSE);
  1649.   }
  1650.  
  1651.   if(ctx->Color.AlphaEnabled) {
  1652.     switch(ctx->Color.AlphaFunc) {
  1653.     case GL_NEVER:
  1654.       grAlphaTestFunction(GR_CMP_NEVER);
  1655.       break;
  1656.     case GL_LESS:
  1657.       grAlphaTestFunction(GR_CMP_LESS);
  1658.       break;
  1659.     case GL_EQUAL:
  1660.       grAlphaTestFunction(GR_CMP_EQUAL);
  1661.       break;
  1662.     case GL_LEQUAL:
  1663.       grAlphaTestFunction(GR_CMP_LEQUAL);
  1664.       break;
  1665.     case GL_GREATER:
  1666.       grAlphaTestFunction(GR_CMP_GREATER);
  1667.       break;
  1668.     case GL_NOTEQUAL:
  1669.       grAlphaTestFunction(GR_CMP_NOTEQUAL);
  1670.       break;
  1671.     case GL_GEQUAL:
  1672.       grAlphaTestFunction(GR_CMP_GEQUAL);
  1673.       break;
  1674.     case GL_ALWAYS:
  1675.       grAlphaTestFunction(GR_CMP_ALWAYS);
  1676.       break;
  1677.     default:
  1678.       break;
  1679.     }
  1680.     grAlphaTestReferenceValue(ctx->Color.AlphaRefUbyte);
  1681.   } else
  1682.     grAlphaTestFunction(GR_CMP_ALWAYS);
  1683.  
  1684.   if(ctx->Texture.Enabled) {
  1685.     switch(ctx->Texture.EnvMode) {
  1686.     case GL_DECAL:
  1687.       guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
  1688.       guTexCombineFunction(GR_TMU0,GR_TEXTURECOMBINE_DECAL);
  1689.       break;
  1690.     case GL_MODULATE:
  1691.       if(ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled)
  1692.         guAlphaSource(GR_ALPHASOURCE_TEXTURE_ALPHA);
  1693.  
  1694.       if(ctx->Light.ShadeModel==GL_SMOOTH)
  1695.         guColorCombineFunction(GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
  1696.       else
  1697.         guColorCombineFunction(GR_COLORCOMBINE_TEXTURE_TIMES_CCRGB);
  1698.  
  1699.       guTexCombineFunction(GR_TMU0,GR_TEXTURECOMBINE_DECAL);
  1700.       break;
  1701.     case GL_BLEND:
  1702. #ifndef FX_SILENT
  1703.       fprintf(stderr,"fx Driver: GL_BLEND not yet supported\n");
  1704. #endif
  1705.       /* TO DO */
  1706.       break;
  1707.     case GL_REPLACE:
  1708.       if(ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled)
  1709.         guAlphaSource(GR_ALPHASOURCE_TEXTURE_ALPHA);
  1710.  
  1711.       guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
  1712.       guTexCombineFunction(GR_TMU0,GR_TEXTURECOMBINE_DECAL);
  1713.       break;
  1714.     default:
  1715. #ifndef FX_SILENT
  1716.       fprintf(stderr,"fx Driver: %x Texture.EnvMode not yet supported\n",ctx->Texture.EnvMode);
  1717. #endif
  1718.       break;
  1719.     }
  1720.   } else {
  1721.     if(ctx->Light.ShadeModel==GL_SMOOTH)
  1722.       guColorCombineFunction(GR_COLORCOMBINE_ITRGB);
  1723.     else
  1724.       guColorCombineFunction(GR_COLORCOMBINE_CCRGB);
  1725.       
  1726.     grTexCombineFunction(GR_TMU0,GR_TEXTURECOMBINE_ONE);
  1727.   }
  1728.  
  1729.   if(ctx->Depth.Test) {
  1730.     if((ctx->ProjectionMatrix[15]==0.0f) &&
  1731.        (ctx->Viewport.Near==0.0) && (ctx->Viewport.Far==1.0)) {
  1732.       grDepthBufferMode(GR_DEPTHBUFFER_WBUFFER);
  1733.       fxMesa->wbuffer=1;
  1734.     } else {
  1735.       grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER); 
  1736.       fxMesa->wbuffer=0;
  1737.     }
  1738.  
  1739.     switch(ctx->Depth.Func) {
  1740.     case GL_NEVER:
  1741.       grDepthBufferFunction(GR_CMP_NEVER);
  1742.       break;
  1743.     case GL_LESS:
  1744.       grDepthBufferFunction(GR_CMP_LESS);
  1745.       break;
  1746.     case GL_GEQUAL:
  1747.       grDepthBufferFunction(GR_CMP_GEQUAL);
  1748.       break;
  1749.     case GL_LEQUAL:
  1750.       grDepthBufferFunction(GR_CMP_LEQUAL);
  1751.       break;
  1752.     case GL_GREATER:
  1753.       grDepthBufferFunction(GR_CMP_GREATER);
  1754.       break;
  1755.     case GL_NOTEQUAL:
  1756.       grDepthBufferFunction(GR_CMP_NOTEQUAL);
  1757.       break;
  1758.     case GL_EQUAL:
  1759.       grDepthBufferFunction(GR_CMP_EQUAL);
  1760.       break;
  1761.     case GL_ALWAYS:
  1762.       grDepthBufferFunction(GR_CMP_ALWAYS);
  1763.       break;
  1764.     default:
  1765.       break;
  1766.     }
  1767.  
  1768.     if(ctx->Depth.Mask)
  1769.       grDepthMask(FXTRUE);
  1770.     else
  1771.       grDepthMask(FXFALSE);
  1772.   } else {
  1773.     grDepthBufferFunction(GR_CMP_ALWAYS);
  1774.     grDepthMask(FXFALSE);
  1775.   }
  1776.  
  1777.   if(ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST) {
  1778.     grFogMode(GR_FOG_WITH_TABLE);
  1779.     grFogColorValue FXCOLOR((unsigned int)(255*ctx->Fog.Color[0]), 
  1780.                             (unsigned int)(255*ctx->Fog.Color[1]),
  1781.                             (unsigned int)(255*ctx->Fog.Color[2]), 
  1782.                             (unsigned int)(255*ctx->Fog.Color[3]));
  1783.  
  1784.     if((fxMesa->fogtablemode!=ctx->Fog.Mode) ||
  1785.        (fxMesa->fogdensity!=ctx->Fog.Density)) {
  1786.       float wscale = ((fxMesaContext)ctx->DriverCtx)->wscale;
  1787.       switch(ctx->Fog.Mode) {
  1788.       case GL_LINEAR:
  1789.         guFogGenerateLinear(fxMesa->fogtable,
  1790.                             ctx->Fog.Start/wscale,
  1791.                             ctx->Fog.End/wscale);
  1792.         break;
  1793.       case GL_EXP:
  1794.         guFogGenerateExp(fxMesa->fogtable,ctx->Fog.Density*wscale);
  1795.         break;
  1796.       case GL_EXP2:
  1797.         guFogGenerateExp2(fxMesa->fogtable,ctx->Fog.Density*wscale);
  1798.         break;
  1799.       default: /* That should never happen */
  1800.         break; 
  1801.       }
  1802.          
  1803.       fxMesa->fogtablemode=ctx->Fog.Mode;
  1804.       fxMesa->fogdensity=ctx->Fog.Density;
  1805.     }
  1806.       
  1807.     grFogTable(fxMesa->fogtable);
  1808.   } else
  1809.     grFogMode(GR_FOG_DISABLE);
  1810. }
  1811.  
  1812.  
  1813. static const char *renderer_string(void)
  1814. {
  1815.   return "Glide";
  1816. }
  1817.  
  1818.  
  1819. /*
  1820.  * The 3Dfx Global Palette extension for GLQuake.
  1821.  * More a trick than a real extesion, use the shared global
  1822.  * palette extension. 
  1823.  */
  1824. void APIENTRY gl3DfxSetPaletteEXT(GLuint *pal)
  1825. {
  1826. #if defined(DEBUG_FXMESA)
  1827.   int i;
  1828.  
  1829.   fprintf(stderr,"fxmesa: gl3DfxSetPaletteEXT()\n");
  1830.  
  1831.   for(i=0;i<256;i++)
  1832.     fprintf(stderr,"%x\n",pal[i]);
  1833. #endif
  1834.  
  1835.   if(CurrentfxMesaCtx) {
  1836.     CurrentfxMesaCtx->globalpalette_texture=1;
  1837.     grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal); 
  1838.   }
  1839. }
  1840.  
  1841.  
  1842. static void setup_dd_pointers(GLcontext *ctx)
  1843. {
  1844. #if defined(DEBUG_FXMESA)
  1845.   fprintf(stderr,"fxmesa: fx_mesa_setup_dd_pointers()\n");
  1846. #endif
  1847.  
  1848.   ctx->Driver.UpdateState=setup_dd_pointers;
  1849.          
  1850.   ctx->Driver.RendererString=renderer_string;
  1851.  
  1852.   ctx->Driver.NearFar=SetNearFar;
  1853.  
  1854.   ctx->Driver.ClearIndex=NULL;
  1855.   ctx->Driver.ClearColor=clear_color;
  1856.   ctx->Driver.Clear=clear;
  1857.  
  1858.   ctx->Driver.Index=NULL;
  1859.   ctx->Driver.Color=set_color;
  1860.  
  1861.   ctx->Driver.SetBuffer=set_buffer;
  1862.   ctx->Driver.GetBufferSize=buffer_size;
  1863.  
  1864.   ctx->Driver.AllocDepthBuffer=alloc_depth_buffer;
  1865.   ctx->Driver.ClearDepthBuffer=clear_depth_buffer;
  1866.  
  1867.   /* acc. functions*/
  1868.  
  1869.   setup_fx_units(ctx);
  1870.  
  1871.   ctx->Driver.PointsFunc=choose_points_function(ctx);
  1872.   ctx->Driver.LineFunc=choose_line_function(ctx);
  1873.   ctx->Driver.TriangleFunc=choose_triangle_function(ctx);
  1874.   ctx->Driver.QuadFunc=choose_quad_function(ctx);
  1875.   ctx->Driver.RectFunc=NULL;
  1876.  
  1877.   ctx->Driver.Bitmap=drawbitmap;
  1878.   ctx->Driver.DrawPixels=NULL;
  1879.  
  1880.   ctx->Driver.RasterSetup=choose_setup_function(ctx);
  1881.   ctx->Driver.RenderVB=NULL;
  1882.  
  1883.   ctx->Driver.Finish=flush;
  1884.   ctx->Driver.Flush=finish;
  1885.  
  1886.   ctx->Driver.TexEnv=texenv;
  1887.   ctx->Driver.TexImage=teximg;
  1888.   ctx->Driver.TexParameter=texparam;
  1889.   ctx->Driver.BindTexture=texbind;
  1890.   ctx->Driver.DeleteTexture=texdel;
  1891.   ctx->Driver.UpdateTexturePalette=texpalette;
  1892.   ctx->Driver.UseGlobalTexturePalette=useglbtexpalette;
  1893.  
  1894.   ctx->Driver.WriteColorSpan      =write_color_span;
  1895.   ctx->Driver.WriteMonocolorSpan  =write_monocolor_span;
  1896.   ctx->Driver.WriteColorPixels    =NULL;
  1897.   ctx->Driver.WriteMonocolorPixels=NULL;
  1898.   ctx->Driver.WriteIndexSpan      =NULL;
  1899.   ctx->Driver.WriteMonoindexSpan  =NULL;
  1900.   ctx->Driver.WriteIndexPixels    =NULL;
  1901.   ctx->Driver.WriteMonoindexPixels=NULL;
  1902.  
  1903.   ctx->Driver.ReadIndexSpan=NULL;
  1904.   ctx->Driver.ReadColorSpan=read_color_span;
  1905.   ctx->Driver.ReadIndexPixels=NULL;
  1906.   ctx->Driver.ReadColorPixels=NULL;
  1907. }
  1908.  
  1909.  
  1910. #define NUM_RESOLUTIONS 3
  1911.  
  1912. static resolutions[NUM_RESOLUTIONS][3]={ 
  1913.   /*
  1914.     { 320, 200, GR_RESOLUTION_320x200 }
  1915.     { 320, 240, GR_RESOLUTION_320x240 },
  1916.     { 400, 256, GR_RESOLUTION_400x256 },
  1917.     { 512, 256, GR_RESOLUTION_512x256 },
  1918.   */
  1919.   { 512, 384, GR_RESOLUTION_512x384 },
  1920.   /*
  1921.   { 640, 200, GR_RESOLUTION_640x200 },
  1922.   { 640, 350, GR_RESOLUTION_640x350 },
  1923.   */
  1924.   { 640, 400, GR_RESOLUTION_640x400 },
  1925.   { 640, 480, GR_RESOLUTION_640x480 }
  1926.   /*,
  1927.     { 800, 600, GR_RESOLUTION_800x600 },
  1928.     { 856, 480, GR_RESOLUTION_856x480 },
  1929.     { 960, 720, GR_RESOLUTION_960x720 }
  1930.     */
  1931. };
  1932.  
  1933. GrScreenResolution_t bestResolution(int width, int height)
  1934. {
  1935.   int i;
  1936.  
  1937.   for(i=0;i<NUM_RESOLUTIONS;i++)
  1938.     if((width<=resolutions[i][0]) && (height<=resolutions[i][1]))
  1939.       return resolutions[i][2];
  1940.         
  1941.   return GR_RESOLUTION_640x480;
  1942. }
  1943.  
  1944.  
  1945. fxMesaContext fxMesaCreateBestContext(GLuint win,GLint width, GLint height,
  1946.                                       const GLint attribList[])
  1947. {
  1948.   GrScreenRefresh_t refresh;
  1949.  
  1950.   refresh=GR_REFRESH_75Hz;
  1951.  
  1952.   if (getenv("SST_SCREENREFRESH")) {
  1953.     if (!strcmp(getenv("SST_SCREENREFRESH"),"60"))
  1954.       refresh=GR_REFRESH_60Hz;
  1955.     if (!strcmp(getenv("SST_SCREENREFRESH"),"70"))
  1956.       refresh=GR_REFRESH_70Hz;
  1957.     if (!strcmp(getenv("SST_SCREENREFRESH"),"72"))
  1958.       refresh=GR_REFRESH_72Hz;
  1959.     if (!strcmp(getenv("SST_SCREENREFRESH"),"75"))
  1960.       refresh=GR_REFRESH_75Hz;
  1961.     if (!strcmp(getenv("SST_SCREENREFRESH"),"80"))
  1962.       refresh=GR_REFRESH_80Hz;
  1963.     if (!strcmp(getenv("SST_SCREENREFRESH"),"85"))
  1964.       refresh=GR_REFRESH_85Hz;
  1965.     if (!strcmp(getenv("SST_SCREENREFRESH"),"90"))
  1966.       refresh=GR_REFRESH_90Hz;
  1967.     if (!strcmp(getenv("SST_SCREENREFRESH"),"100"))
  1968.       refresh=GR_REFRESH_100Hz;
  1969.     if (!strcmp(getenv("SST_SCREENREFRESH"),"120"))
  1970.       refresh=GR_REFRESH_120Hz;
  1971.   }
  1972.  
  1973.   return fxMesaCreateContext(win,bestResolution(width,height),
  1974.                              refresh,attribList);
  1975. }
  1976.  
  1977. /*
  1978.  * Create a new FX/Mesa context and return a handle to it.
  1979.  */
  1980. fxMesaContext fxMesaCreateContext(GLuint win,GrScreenResolution_t res,
  1981.                                   GrScreenRefresh_t ref,
  1982.                                   const GLint attribList[])
  1983. {
  1984.   fxMesaContext ctx;
  1985.   int i,type;
  1986.   GLboolean doubleBuffer=GL_FALSE;
  1987.   GLboolean alphaBuffer=GL_FALSE;
  1988.   GLboolean verbose=GL_FALSE;
  1989.   GLint depthSize=0;
  1990.   GLint stencilSize=0;
  1991.   GLint accumSize=0;
  1992.  
  1993.   if(getenv("MESA_FX_INFO"))
  1994.     verbose=GL_TRUE;
  1995.  
  1996.   i=0;
  1997.   while (attribList[i]!=FXMESA_NONE) {
  1998.     switch (attribList[i]) {
  1999.     case FXMESA_DOUBLEBUFFER:
  2000.       doubleBuffer = GL_TRUE;
  2001.       break;
  2002.     case FXMESA_ALPHA_SIZE:
  2003.       i++;
  2004.       alphaBuffer = attribList[i] > 0;
  2005.       break;
  2006.     case FXMESA_DEPTH_SIZE:
  2007.       i++;
  2008.       depthSize = attribList[i];
  2009.       break;
  2010.     case FXMESA_STENCIL_SIZE:
  2011.       i++;
  2012.       stencilSize = attribList[i];
  2013.       break;
  2014.     case FXMESA_ACCUM_SIZE:
  2015.       i++;
  2016.       accumSize = attribList[i];
  2017.       break;
  2018.     default:
  2019.       return NULL;
  2020.     }
  2021.     i++;
  2022.   }
  2023.  
  2024.  
  2025. #if defined(DEBUG_FXMESA)
  2026.   fprintf(stderr,"fxmesa: fxMesaCreateContext()\n");
  2027. #endif
  2028.  
  2029.   if(verbose)
  2030.     fprintf(stderr,"Mesa fx Voodoo Device Driver v0.20\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
  2031.  
  2032.  
  2033.   if((type=fxQueryHardware()) >= 0) {
  2034.     if(type==GR_SSTTYPE_VOODOO)
  2035.       win=0;
  2036.  
  2037. #if USE_GLIDE_FULLSCREEN
  2038.     if(!grSstOpen(res,                  /* resolution */
  2039.                   ref,                  /* refresh */
  2040.                   GR_COLORFORMAT_ABGR,  /* pixel format */
  2041.                   GR_ORIGIN_LOWER_LEFT, /* origin */
  2042.                   GR_SMOOTHING_ENABLE,  /* smoothing mode */
  2043.                   2))                   /* num buffers */
  2044.       return NULL;
  2045. #else   /* Glide in a window */
  2046.     if(!grSstWinOpen((FxU32)win,res,ref,
  2047.                      GR_COLORFORMAT_ABGR,GR_ORIGIN_LOWER_LEFT,2,1))
  2048.       return NULL;
  2049. #endif
  2050.  
  2051.     if(verbose)
  2052.       fprintf(stderr,"Glide screen size: %dx%d\n",
  2053.           (int)grSstScreenWidth(),(int)grSstScreenHeight());
  2054.   } else {
  2055.     fprintf(stderr,"fxmesa: ERROR no Voodoo Graphics or Voodoo Rush !\n");
  2056.     return NULL;
  2057.   }
  2058.  
  2059.   ctx=(fxMesaContext)malloc(sizeof(struct fx_mesa_context));
  2060.   if(!ctx)
  2061.     return NULL;
  2062.  
  2063.   ctx->width=grSstScreenWidth();
  2064.   ctx->height=grSstScreenHeight();
  2065.   ctx->double_buffer=doubleBuffer;
  2066.   ctx->verbose=verbose;
  2067.   ctx->fixedpalette_texture=0;
  2068.   ctx->globalpalette_texture=0;
  2069.  
  2070.   ctx->color=FXCOLOR(255,255,255,255);
  2071.   ctx->clearc=0;
  2072.   ctx->cleara=0;
  2073.  
  2074.   ctx->stats.swapbuffer=0;
  2075.   ctx->stats.reqtexupload=0;
  2076.   ctx->stats.texupload=0;
  2077.   ctx->stats.memtexupload=0;
  2078.  
  2079.   inittmmanager(ctx);
  2080.  
  2081.   grColorMask(FXTRUE,FXFALSE);
  2082.   if (doubleBuffer) {
  2083.     ctx->currentfb=GR_BUFFER_BACKBUFFER;
  2084.     grRenderBuffer(GR_BUFFER_BACKBUFFER);
  2085.   } else {
  2086.     ctx->currentfb=GR_BUFFER_FRONTBUFFER;
  2087.     grRenderBuffer(GR_BUFFER_FRONTBUFFER);
  2088.   }
  2089.  
  2090.   ctx->gl_vis = gl_create_visual(GL_TRUE,     /* RGB mode */
  2091.                                  alphaBuffer,
  2092.                                  doubleBuffer,
  2093.                                  depthSize,   /* depth_size */
  2094.                                  stencilSize, /* stencil_size */
  2095.                                  accumSize,   /* accum_size */
  2096.                                  0,           /* index bits */
  2097.                                  255.0,       /* color scales */
  2098.                                  255.0,
  2099.                                  255.0,
  2100.                                  255.0,
  2101.                                  5, 6, 5, 0);
  2102.  
  2103.   ctx->gl_ctx = gl_create_context(ctx->gl_vis,
  2104.                                   NULL,  /* share list context */
  2105.                                   (void *) ctx);
  2106.  
  2107.   ctx->gl_buffer = gl_create_framebuffer(ctx->gl_vis);
  2108.  
  2109.   setup_dd_pointers(ctx->gl_ctx);
  2110.  
  2111.   SetNearFar(ctx->gl_ctx,1.0,100.0);
  2112.  
  2113.   return ctx;
  2114. }
  2115.  
  2116.  
  2117. /*
  2118.  * Destroy the given FX/Mesa context.
  2119.  */
  2120. void fxMesaDestroyContext(fxMesaContext ctx)
  2121. {
  2122. #if defined(DEBUG_FXMESA)
  2123.   fprintf(stderr,"fxmesa: fxMesaDestroyContext()\n");
  2124. #endif
  2125.  
  2126.   if(ctx) {
  2127.     gl_destroy_visual(ctx->gl_vis);
  2128.     gl_destroy_context(ctx->gl_ctx);
  2129.     gl_destroy_framebuffer(ctx->gl_buffer);
  2130.  
  2131.     fxCloseHardware();
  2132.  
  2133.     if(ctx->verbose) {
  2134.       fprintf(stderr,"Misc Stats:\n");
  2135.       fprintf(stderr,"  # swap buffer: %u\n",ctx->stats.swapbuffer);
  2136.  
  2137.       if(!ctx->stats.swapbuffer)
  2138.     ctx->stats.swapbuffer=1;
  2139.  
  2140.       fprintf(stderr,"Textures Stats:\n");
  2141.       fprintf(stderr,"  # request to TMM to upload a texture objects: %u\n",
  2142.           ctx->stats.reqtexupload);
  2143.       fprintf(stderr,"  # request to TMM to upload a texture objects per swapbuffer: %.2f\n",
  2144.           ctx->stats.reqtexupload/(float)ctx->stats.swapbuffer);
  2145.       fprintf(stderr,"  # texture objects uploaded: %u\n",
  2146.           ctx->stats.texupload);
  2147.       fprintf(stderr,"  # texture objects uploaded per swapbuffer: %.2f\n",
  2148.           ctx->stats.texupload/(float)ctx->stats.swapbuffer);
  2149.       fprintf(stderr,"  # MBs uploaded to texture memory: %.2f\n",
  2150.           ctx->stats.memtexupload/(float)(1<<20));
  2151.       fprintf(stderr,"  # MBs uploaded to texture memory per swapbuffer: %.2f\n",
  2152.           (ctx->stats.memtexupload/(float)ctx->stats.swapbuffer)/(float)(1<<20));
  2153.     }
  2154.  
  2155.     closetmmanager(ctx);
  2156.  
  2157.     free(ctx);
  2158.   }
  2159.  
  2160.   if(ctx==CurrentfxMesaCtx)
  2161.     CurrentfxMesaCtx=NULL;
  2162. }
  2163.  
  2164. /*
  2165.  * Make the specified FX/Mesa context the current one.
  2166.  */
  2167. void fxMesaMakeCurrent(fxMesaContext ctx)
  2168. {
  2169. #if defined(DEBUG_FXMESA)
  2170.   fprintf(stderr,"fxmesa: fxMesaMakeCurrent()\n");
  2171. #endif
  2172.  
  2173.   if(!ctx) {
  2174.     gl_make_current(NULL,NULL);
  2175.     CurrentfxMesaCtx=NULL;
  2176.  
  2177.     return;
  2178.   }
  2179.  
  2180.   CurrentfxMesaCtx=ctx;
  2181.  
  2182.   gl_make_current(ctx->gl_ctx,ctx->gl_buffer);
  2183.  
  2184.   setup_dd_pointers(ctx->gl_ctx);
  2185.  
  2186.   /* The first time we call MakeCurrent we set the initial viewport size */
  2187.   if (ctx->gl_ctx->Viewport.Width==0)
  2188.     gl_Viewport(ctx->gl_ctx,0,0,ctx->width,ctx->height);
  2189. }
  2190.  
  2191.  
  2192. /*
  2193.  * Swap front/back buffers for current context if double buffered.
  2194.  */
  2195. void fxMesaSwapBuffers(void)
  2196. {
  2197. #if defined(DEBUG_FXMESA)
  2198.   fprintf(stderr,"fxmesa: ------------------------------- fxMesaSwapBuffers() -------------------------------\n");
  2199. #endif
  2200.  
  2201.   if(CurrentfxMesaCtx)
  2202.     if(CurrentfxMesaCtx->double_buffer) {
  2203.       grBufferSwap(1);
  2204.  
  2205.       CurrentfxMesaCtx->stats.swapbuffer++;
  2206.     }
  2207. }
  2208.  
  2209.  
  2210. /*
  2211.  * Activate/Deactivate Texture Palette
  2212.  */
  2213. void fxMesaTextureUsePalette(GLboolean v)
  2214. {
  2215. #if defined(DEBUG_FXMESA)
  2216.   fprintf(stderr,"fxmesa: fxMesaTextureUsePalette()\n");
  2217. #endif
  2218.  
  2219.   if(CurrentfxMesaCtx)
  2220.     CurrentfxMesaCtx->fixedpalette_texture=v;
  2221. }
  2222.  
  2223.  
  2224. #if defined(__WIN32__)
  2225. static int cleangraphics(void)
  2226. {
  2227.   fxMesaDestroyContext(CurrentfxMesaCtx);
  2228.  
  2229.   return 0;
  2230. }
  2231. #elif defined(__linux__)
  2232. static void cleangraphics(void)
  2233. {
  2234.   fxMesaDestroyContext(CurrentfxMesaCtx);
  2235. }
  2236. #endif
  2237.  
  2238.  
  2239. /*
  2240.  * Query 3Dfx hardware presence/kind
  2241.  */
  2242. int fxQueryHardware(void)
  2243. {
  2244.   if(!glideInitialized) {
  2245.       grGlideInit();
  2246.       if(grSstQueryHardware(&hwconfig)) {
  2247.       grSstSelect(0);
  2248.       _3dfxPresent=1;
  2249.  
  2250.       if(getenv("MESA_FX_INFO")) {
  2251.         char buf[80];
  2252.             
  2253.         grGlideGetVersion(buf);
  2254.         fprintf(stderr,"Using Glide V%s\nNumber of boards: %d\n",buf,hwconfig.num_sst);
  2255.       }
  2256.       } else
  2257.     _3dfxPresent=0;
  2258.  
  2259.       glideInitialized=1;
  2260.  
  2261. #if defined(__WIN32__)
  2262.       onexit((_onexit_t)cleangraphics);
  2263. #elif defined(__linux__)
  2264.       atexit(cleangraphics);
  2265. #endif
  2266.     }
  2267.  
  2268.   if(!_3dfxPresent)
  2269.     return(-1);
  2270.   else
  2271.     return(hwconfig.SSTs[0].type);
  2272. }
  2273.  
  2274.  
  2275. /*
  2276.  * Shutdown Glide library
  2277.  */
  2278. int fxCloseHardware(void)
  2279. {
  2280.   if(glideInitialized) {
  2281.     if(getenv("MESA_FX_INFO")) {
  2282.       GrSstPerfStats_t        st;
  2283.  
  2284.       grSstPerfStats(&st);
  2285.       fprintf(stderr,"Pixels Stats:\n");
  2286.       fprintf(stderr,"  # pixels processed (minus buffer clears): %u\n",(unsigned)st.pixelsIn);
  2287.       fprintf(stderr,"  # pixels not drawn due to chroma key test failure: %u\n",(unsigned)st.chromaFail);
  2288.       fprintf(stderr,"  # pixels not drawn due to depth test failure: %u\n",(unsigned)st.zFuncFail);
  2289.       fprintf(stderr,"  # pixels not drawn due to alpha test failure: %u\n",(unsigned)st.aFuncFail);
  2290.       fprintf(stderr,"  # pixels drawn (including buffer clears and LFB writes): %u\n",(unsigned)st.pixelsOut);
  2291.     }
  2292.  
  2293.     grGlideShutdown();
  2294.     glideInitialized = 0;
  2295.   }
  2296.  
  2297.   return 0;
  2298. }
  2299.  
  2300.  
  2301. #else
  2302.  
  2303.  
  2304. /*
  2305.  * Need this to provide at least one external definition.
  2306.  */
  2307.  
  2308. int gl_fx_dummy_function1(void)
  2309. {
  2310.   return 0;
  2311. }
  2312.  
  2313. #endif  /* FX */
  2314.