home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / gl_draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  29.4 KB  |  1,379 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. // draw.c -- this is the only file outside the refresh that touches the
  22. // vid buffer
  23.  
  24. #include "quakedef.h"
  25.  
  26. extern unsigned char d_15to8table[65536];
  27. extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor;
  28.  
  29. cvar_t        gl_nobind = {"gl_nobind", "0"};
  30. cvar_t        gl_max_size = {"gl_max_size", "1024"};
  31. cvar_t        gl_picmip = {"gl_picmip", "0"};
  32.  
  33. byte        *draw_chars;                // 8*8 graphic characters
  34. qpic_t        *draw_disc;
  35. qpic_t        *draw_backtile;
  36.  
  37. int            translate_texture;
  38. int            char_texture;
  39. int            cs_texture; // crosshair texture
  40.  
  41. static byte cs_data[64] = {
  42.     0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  43.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  44.     0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  45.     0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff,
  46.     0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  47.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  48.     0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  49.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  50. };
  51.  
  52.  
  53. typedef struct
  54. {
  55.     int        texnum;
  56.     float    sl, tl, sh, th;
  57. } glpic_t;
  58.  
  59. byte        conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
  60. qpic_t        *conback = (qpic_t *)&conback_buffer;
  61.  
  62. int        gl_lightmap_format = 4;
  63. int        gl_solid_format = 3;
  64. int        gl_alpha_format = 4;
  65.  
  66. int        gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
  67. int        gl_filter_max = GL_LINEAR;
  68.  
  69.  
  70. int        texels;
  71.  
  72. typedef struct
  73. {
  74.     int        texnum;
  75.     char    identifier[64];
  76.     int        width, height;
  77.     qboolean    mipmap;
  78. } gltexture_t;
  79.  
  80. #define    MAX_GLTEXTURES    1024
  81. gltexture_t    gltextures[MAX_GLTEXTURES];
  82. int            numgltextures;
  83.  
  84. void GL_Bind (int texnum)
  85. {
  86.     if (gl_nobind.value)
  87.         texnum = char_texture;
  88.     if (currenttexture == texnum)
  89.         return;
  90.     currenttexture = texnum;
  91. #ifdef _WIN32
  92.     bindTexFunc (GL_TEXTURE_2D, texnum);
  93. #else
  94.     glBindTexture (GL_TEXTURE_2D, texnum);
  95. #endif
  96. }
  97.  
  98.  
  99. /*
  100. =============================================================================
  101.  
  102.   scrap allocation
  103.  
  104.   Allocate all the little status bar obejcts into a single texture
  105.   to crutch up stupid hardware / drivers
  106.  
  107. =============================================================================
  108. */
  109.  
  110. #define    MAX_SCRAPS        1
  111. #define    BLOCK_WIDTH        256
  112. #define    BLOCK_HEIGHT    256
  113.  
  114. int            scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
  115. byte        scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
  116. qboolean    scrap_dirty;
  117. int            scrap_texnum;
  118.  
  119. // returns a texture number and the position inside it
  120. int Scrap_AllocBlock (int w, int h, int *x, int *y)
  121. {
  122.     int        i, j;
  123.     int        best, best2;
  124.     int        texnum;
  125.  
  126.     for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
  127.     {
  128.         best = BLOCK_HEIGHT;
  129.  
  130.         for (i=0 ; i<BLOCK_WIDTH-w ; i++)
  131.         {
  132.             best2 = 0;
  133.  
  134.             for (j=0 ; j<w ; j++)
  135.             {
  136.                 if (scrap_allocated[texnum][i+j] >= best)
  137.                     break;
  138.                 if (scrap_allocated[texnum][i+j] > best2)
  139.                     best2 = scrap_allocated[texnum][i+j];
  140.             }
  141.             if (j == w)
  142.             {    // this is a valid spot
  143.                 *x = i;
  144.                 *y = best = best2;
  145.             }
  146.         }
  147.  
  148.         if (best + h > BLOCK_HEIGHT)
  149.             continue;
  150.  
  151.         for (i=0 ; i<w ; i++)
  152.             scrap_allocated[texnum][*x + i] = best + h;
  153.  
  154.         return texnum;
  155.     }
  156.  
  157.     Sys_Error ("Scrap_AllocBlock: full");
  158.     return 0;
  159. }
  160.  
  161. int    scrap_uploads;
  162.  
  163. void Scrap_Upload (void)
  164. {
  165.     scrap_uploads++;
  166.     GL_Bind(scrap_texnum);
  167.     GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
  168.     scrap_dirty = false;
  169. }
  170.  
  171. //=============================================================================
  172. /* Support Routines */
  173.  
  174. typedef struct cachepic_s
  175. {
  176.     char        name[MAX_QPATH];
  177.     qpic_t        pic;
  178.     byte        padding[32];    // for appended glpic
  179. } cachepic_t;
  180.  
  181. #define    MAX_CACHED_PICS        128
  182. cachepic_t    menu_cachepics[MAX_CACHED_PICS];
  183. int            menu_numcachepics;
  184.  
  185. byte        menuplyr_pixels[4096];
  186.  
  187. int        pic_texels;
  188. int        pic_count;
  189.  
  190. qpic_t *Draw_PicFromWad (char *name)
  191. {
  192.     qpic_t    *p;
  193.     glpic_t    *gl;
  194.  
  195.     p = W_GetLumpName (name);
  196.     gl = (glpic_t *)p->data;
  197.  
  198.     // load little ones into the scrap
  199.     if (p->width < 64 && p->height < 64)
  200.     {
  201.         int        x, y;
  202.         int        i, j, k;
  203.         int        texnum;
  204.  
  205.         texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
  206.         scrap_dirty = true;
  207.         k = 0;
  208.         for (i=0 ; i<p->height ; i++)
  209.             for (j=0 ; j<p->width ; j++, k++)
  210.                 scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
  211.         texnum += scrap_texnum;
  212.         gl->texnum = texnum;
  213.         gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
  214.         gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
  215.         gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
  216.         gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
  217.  
  218.         pic_count++;
  219.         pic_texels += p->width*p->height;
  220.     }
  221.     else
  222.     {
  223.         gl->texnum = GL_LoadPicTexture (p);
  224.         gl->sl = 0;
  225.         gl->sh = 1;
  226.         gl->tl = 0;
  227.         gl->th = 1;
  228.     }
  229.     return p;
  230. }
  231.  
  232.  
  233. /*
  234. ================
  235. Draw_CachePic
  236. ================
  237. */
  238. qpic_t    *Draw_CachePic (char *path)
  239. {
  240.     cachepic_t    *pic;
  241.     int            i;
  242.     qpic_t        *dat;
  243.     glpic_t        *gl;
  244.  
  245.     for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
  246.         if (!strcmp (path, pic->name))
  247.             return &pic->pic;
  248.  
  249.     if (menu_numcachepics == MAX_CACHED_PICS)
  250.         Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
  251.     menu_numcachepics++;
  252.     strcpy (pic->name, path);
  253.  
  254. //
  255. // load the pic from disk
  256. //
  257.     dat = (qpic_t *)COM_LoadTempFile (path);    
  258.     if (!dat)
  259.         Sys_Error ("Draw_CachePic: failed to load %s", path);
  260.     SwapPic (dat);
  261.  
  262.     // HACK HACK HACK --- we need to keep the bytes for
  263.     // the translatable player picture just for the menu
  264.     // configuration dialog
  265.     if (!strcmp (path, "gfx/menuplyr.lmp"))
  266.         memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
  267.  
  268.     pic->pic.width = dat->width;
  269.     pic->pic.height = dat->height;
  270.  
  271.     gl = (glpic_t *)pic->pic.data;
  272.     gl->texnum = GL_LoadPicTexture (dat);
  273.     gl->sl = 0;
  274.     gl->sh = 1;
  275.     gl->tl = 0;
  276.     gl->th = 1;
  277.  
  278.     return &pic->pic;
  279. }
  280.  
  281.  
  282. void Draw_CharToConback (int num, byte *dest)
  283. {
  284.     int        row, col;
  285.     byte    *source;
  286.     int        drawline;
  287.     int        x;
  288.  
  289.     row = num>>4;
  290.     col = num&15;
  291.     source = draw_chars + (row<<10) + (col<<3);
  292.  
  293.     drawline = 8;
  294.  
  295.     while (drawline--)
  296.     {
  297.         for (x=0 ; x<8 ; x++)
  298.             if (source[x] != 255)
  299.                 dest[x] = 0x60 + source[x];
  300.         source += 128;
  301.         dest += 320;
  302.     }
  303.  
  304. }
  305.  
  306. typedef struct
  307. {
  308.     char *name;
  309.     int    minimize, maximize;
  310. } glmode_t;
  311.  
  312. glmode_t modes[] = {
  313.     {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
  314.     {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
  315.     {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
  316.     {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
  317.     {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
  318.     {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
  319. };
  320.  
  321. /*
  322. ===============
  323. Draw_TextureMode_f
  324. ===============
  325. */
  326. void Draw_TextureMode_f (void)
  327. {
  328.     int        i;
  329.     gltexture_t    *glt;
  330.  
  331.     if (Cmd_Argc() == 1)
  332.     {
  333.         for (i=0 ; i< 6 ; i++)
  334.             if (gl_filter_min == modes[i].minimize)
  335.             {
  336.                 Con_Printf ("%s\n", modes[i].name);
  337.                 return;
  338.             }
  339.         Con_Printf ("current filter is unknown???\n");
  340.         return;
  341.     }
  342.  
  343.     for (i=0 ; i< 6 ; i++)
  344.     {
  345.         if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
  346.             break;
  347.     }
  348.     if (i == 6)
  349.     {
  350.         Con_Printf ("bad filter name\n");
  351.         return;
  352.     }
  353.  
  354.     gl_filter_min = modes[i].minimize;
  355.     gl_filter_max = modes[i].maximize;
  356.  
  357.     // change all the existing mipmap texture objects
  358.     for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  359.     {
  360.         if (glt->mipmap)
  361.         {
  362.             GL_Bind (glt->texnum);
  363.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  364.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  365.         }
  366.     }
  367. }
  368.  
  369. /*
  370. ===============
  371. Draw_Init
  372. ===============
  373. */
  374. void Draw_Init (void)
  375. {
  376.     int        i;
  377.     qpic_t    *cb;
  378.     byte    *dest;
  379.     int        x;
  380.     char    ver[40];
  381.     glpic_t    *gl;
  382.     int start;
  383.     byte    *ncdata;
  384.  
  385.     Cvar_RegisterVariable (&gl_nobind);
  386.     Cvar_RegisterVariable (&gl_max_size);
  387.     Cvar_RegisterVariable (&gl_picmip);
  388.  
  389.     // 3dfx can only handle 256 wide textures
  390.     if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
  391.         !Q_strncasecmp ((char *)gl_renderer, "Mesa",4))
  392.         Cvar_Set ("gl_max_size", "256");
  393.  
  394.     Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
  395.  
  396.     // load the console background and the charset
  397.     // by hand, because we need to write the version
  398.     // string into the background before turning
  399.     // it into a texture
  400.     draw_chars = W_GetLumpName ("conchars");
  401.     for (i=0 ; i<256*64 ; i++)
  402.         if (draw_chars[i] == 0)
  403.             draw_chars[i] = 255;    // proper transparent color
  404.  
  405.     // now turn them into textures
  406.     char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
  407. //    Draw_CrosshairAdjust();
  408.     cs_texture = GL_LoadTexture ("crosshair", 8, 8, cs_data, false, true);
  409.  
  410.     start = Hunk_LowMark ();
  411.  
  412.     cb = (qpic_t *)COM_LoadHunkFile ("gfx/conback.lmp");    
  413.     if (!cb)
  414.         Sys_Error ("Couldn't load gfx/conback.lmp");
  415.     SwapPic (cb);
  416.  
  417.     sprintf (ver, "%4.2f", VERSION);
  418.     dest = cb->data + 320 + 320*186 - 11 - 8*strlen(ver);
  419.     for (x=0 ; x<strlen(ver) ; x++)
  420.         Draw_CharToConback (ver[x], dest+(x<<3));
  421.  
  422. #if 0
  423.     conback->width = vid.conwidth;
  424.     conback->height = vid.conheight;
  425.  
  426.     // scale console to vid size
  427.     dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback");
  428.  
  429.     for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth)
  430.     {
  431.         src = cb->data + cb->width * (y*cb->height/vid.conheight);
  432.         if (vid.conwidth == cb->width)
  433.             memcpy (dest, src, vid.conwidth);
  434.         else
  435.         {
  436.             f = 0;
  437.             fstep = cb->width*0x10000/vid.conwidth;
  438.             for (x=0 ; x<vid.conwidth ; x+=4)
  439.             {
  440.                 dest[x] = src[f>>16];
  441.                 f += fstep;
  442.                 dest[x+1] = src[f>>16];
  443.                 f += fstep;
  444.                 dest[x+2] = src[f>>16];
  445.                 f += fstep;
  446.                 dest[x+3] = src[f>>16];
  447.                 f += fstep;
  448.             }
  449.         }
  450.     }
  451. #else
  452.     conback->width = cb->width;
  453.     conback->height = cb->height;
  454.     ncdata = cb->data;
  455. #endif
  456.     
  457.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  458.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  459.  
  460.     gl = (glpic_t *)conback->data;
  461.     gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false);
  462.     gl->sl = 0;
  463.     gl->sh = 1;
  464.     gl->tl = 0;
  465.     gl->th = 1;
  466.     conback->width = vid.conwidth;
  467.     conback->height = vid.conheight;
  468.  
  469.     // free loaded console
  470.     Hunk_FreeToLowMark (start);
  471.  
  472.     // save a texture slot for translated picture
  473.     translate_texture = texture_extension_number++;
  474.  
  475.     // save slots for scraps
  476.     scrap_texnum = texture_extension_number;
  477.     texture_extension_number += MAX_SCRAPS;
  478.  
  479.     //
  480.     // get the other pics we need
  481.     //
  482.     draw_disc = Draw_PicFromWad ("disc");
  483.     draw_backtile = Draw_PicFromWad ("backtile");
  484. }
  485.  
  486.  
  487.  
  488. /*
  489. ================
  490. Draw_Character
  491.  
  492. Draws one 8*8 graphics character with 0 being transparent.
  493. It can be clipped to the top of the screen to allow the console to be
  494. smoothly scrolled off.
  495. ================
  496. */
  497. void Draw_Character (int x, int y, int num)
  498. {
  499.     int                row, col;
  500.     float            frow, fcol, size;
  501.  
  502.     if (num == 32)
  503.         return;        // space
  504.  
  505.     num &= 255;
  506.     
  507.     if (y <= -8)
  508.         return;            // totally off screen
  509.  
  510.     row = num>>4;
  511.     col = num&15;
  512.  
  513.     frow = row*0.0625;
  514.     fcol = col*0.0625;
  515.     size = 0.0625;
  516.  
  517.     GL_Bind (char_texture);
  518.  
  519.     glBegin (GL_QUADS);
  520.     glTexCoord2f (fcol, frow);
  521.     glVertex2f (x, y);
  522.     glTexCoord2f (fcol + size, frow);
  523.     glVertex2f (x+8, y);
  524.     glTexCoord2f (fcol + size, frow + size);
  525.     glVertex2f (x+8, y+8);
  526.     glTexCoord2f (fcol, frow + size);
  527.     glVertex2f (x, y+8);
  528.     glEnd ();
  529. }
  530.  
  531. /*
  532. ================
  533. Draw_String
  534. ================
  535. */
  536. void Draw_String (int x, int y, char *str)
  537. {
  538.     while (*str)
  539.     {
  540.         Draw_Character (x, y, *str);
  541.         str++;
  542.         x += 8;
  543.     }
  544. }
  545.  
  546. /*
  547. ================
  548. Draw_Alt_String
  549. ================
  550. */
  551. void Draw_Alt_String (int x, int y, char *str)
  552. {
  553.     while (*str)
  554.     {
  555.         Draw_Character (x, y, (*str) | 0x80);
  556.         str++;
  557.         x += 8;
  558.     }
  559. }
  560.  
  561. void Draw_Crosshair(void)
  562. {
  563.     int x, y;
  564.     extern vrect_t        scr_vrect;
  565.     unsigned char *pColor;
  566.  
  567.     if (crosshair.value == 2) {
  568.         x = scr_vrect.x + scr_vrect.width/2 - 3 + cl_crossx.value; 
  569.         y = scr_vrect.y + scr_vrect.height/2 - 3 + cl_crossy.value;
  570.  
  571.         glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  572.         pColor = (unsigned char *) &d_8to24table[(byte) crosshaircolor.value];
  573.         glColor4ubv ( pColor );
  574.         GL_Bind (cs_texture);
  575.  
  576.         glBegin (GL_QUADS);
  577.         glTexCoord2f (0, 0);
  578.         glVertex2f (x - 4, y - 4);
  579.         glTexCoord2f (1, 0);
  580.         glVertex2f (x+12, y-4);
  581.         glTexCoord2f (1, 1);
  582.         glVertex2f (x+12, y+12);
  583.         glTexCoord2f (0, 1);
  584.         glVertex2f (x - 4, y+12);
  585.         glEnd ();
  586.         
  587.         glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
  588.     } else if (crosshair.value)
  589.         Draw_Character (scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value, 
  590.             scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value, 
  591.             '+');
  592. }
  593.  
  594.  
  595. /*
  596. ================
  597. Draw_DebugChar
  598.  
  599. Draws a single character directly to the upper right corner of the screen.
  600. This is for debugging lockups by drawing different chars in different parts
  601. of the code.
  602. ================
  603. */
  604. void Draw_DebugChar (char num)
  605. {
  606. }
  607.  
  608. /*
  609. =============
  610. Draw_Pic
  611. =============
  612. */
  613. void Draw_Pic (int x, int y, qpic_t *pic)
  614. {
  615.     glpic_t            *gl;
  616.  
  617.     if (scrap_dirty)
  618.         Scrap_Upload ();
  619.     gl = (glpic_t *)pic->data;
  620.     glColor4f (1,1,1,1);
  621.     GL_Bind (gl->texnum);
  622.     glBegin (GL_QUADS);
  623.     glTexCoord2f (gl->sl, gl->tl);
  624.     glVertex2f (x, y);
  625.     glTexCoord2f (gl->sh, gl->tl);
  626.     glVertex2f (x+pic->width, y);
  627.     glTexCoord2f (gl->sh, gl->th);
  628.     glVertex2f (x+pic->width, y+pic->height);
  629.     glTexCoord2f (gl->sl, gl->th);
  630.     glVertex2f (x, y+pic->height);
  631.     glEnd ();
  632. }
  633.  
  634. /*
  635. =============
  636. Draw_AlphaPic
  637. =============
  638. */
  639. void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
  640. {
  641.     glpic_t            *gl;
  642.  
  643.     if (scrap_dirty)
  644.         Scrap_Upload ();
  645.     gl = (glpic_t *)pic->data;
  646.     glDisable(GL_ALPHA_TEST);
  647.     glEnable (GL_BLEND);
  648. //    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  649.     glCullFace(GL_FRONT);
  650.     glColor4f (1,1,1,alpha);
  651.     GL_Bind (gl->texnum);
  652.     glBegin (GL_QUADS);
  653.     glTexCoord2f (gl->sl, gl->tl);
  654.     glVertex2f (x, y);
  655.     glTexCoord2f (gl->sh, gl->tl);
  656.     glVertex2f (x+pic->width, y);
  657.     glTexCoord2f (gl->sh, gl->th);
  658.     glVertex2f (x+pic->width, y+pic->height);
  659.     glTexCoord2f (gl->sl, gl->th);
  660.     glVertex2f (x, y+pic->height);
  661.     glEnd ();
  662.     glColor4f (1,1,1,1);
  663.     glEnable(GL_ALPHA_TEST);
  664.     glDisable (GL_BLEND);
  665. }
  666.  
  667. void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
  668. {
  669.     glpic_t            *gl;
  670.     float newsl, newtl, newsh, newth;
  671.     float oldglwidth, oldglheight;
  672.  
  673.     if (scrap_dirty)
  674.         Scrap_Upload ();
  675.     gl = (glpic_t *)pic->data;
  676.     
  677.     oldglwidth = gl->sh - gl->sl;
  678.     oldglheight = gl->th - gl->tl;
  679.  
  680.     newsl = gl->sl + (srcx*oldglwidth)/pic->width;
  681.     newsh = newsl + (width*oldglwidth)/pic->width;
  682.  
  683.     newtl = gl->tl + (srcy*oldglheight)/pic->height;
  684.     newth = newtl + (height*oldglheight)/pic->height;
  685.     
  686.     glColor4f (1,1,1,1);
  687.     GL_Bind (gl->texnum);
  688.     glBegin (GL_QUADS);
  689.     glTexCoord2f (newsl, newtl);
  690.     glVertex2f (x, y);
  691.     glTexCoord2f (newsh, newtl);
  692.     glVertex2f (x+width, y);
  693.     glTexCoord2f (newsh, newth);
  694.     glVertex2f (x+width, y+height);
  695.     glTexCoord2f (newsl, newth);
  696.     glVertex2f (x, y+height);
  697.     glEnd ();
  698. }
  699.  
  700. /*
  701. =============
  702. Draw_TransPic
  703. =============
  704. */
  705. void Draw_TransPic (int x, int y, qpic_t *pic)
  706. {
  707.  
  708.     if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  709.          (unsigned)(y + pic->height) > vid.height)
  710.     {
  711.         Sys_Error ("Draw_TransPic: bad coordinates");
  712.     }
  713.         
  714.     Draw_Pic (x, y, pic);
  715. }
  716.  
  717.  
  718. /*
  719. =============
  720. Draw_TransPicTranslate
  721.  
  722. Only used for the player color selection menu
  723. =============
  724. */
  725. void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
  726. {
  727.     int                v, u, c;
  728.     unsigned        trans[64*64], *dest;
  729.     byte            *src;
  730.     int                p;
  731.  
  732.     GL_Bind (translate_texture);
  733.  
  734.     c = pic->width * pic->height;
  735.  
  736.     dest = trans;
  737.     for (v=0 ; v<64 ; v++, dest += 64)
  738.     {
  739.         src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
  740.         for (u=0 ; u<64 ; u++)
  741.         {
  742.             p = src[(u*pic->width)>>6];
  743.             if (p == 255)
  744.                 dest[u] = p;
  745.             else
  746.                 dest[u] =  d_8to24table[translation[p]];
  747.         }
  748.     }
  749.  
  750.     glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  751.  
  752.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  753.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  754.  
  755.     glColor3f (1,1,1);
  756.     glBegin (GL_QUADS);
  757.     glTexCoord2f (0, 0);
  758.     glVertex2f (x, y);
  759.     glTexCoord2f (1, 0);
  760.     glVertex2f (x+pic->width, y);
  761.     glTexCoord2f (1, 1);
  762.     glVertex2f (x+pic->width, y+pic->height);
  763.     glTexCoord2f (0, 1);
  764.     glVertex2f (x, y+pic->height);
  765.     glEnd ();
  766. }
  767.  
  768.  
  769. /*
  770. ================
  771. Draw_ConsoleBackground
  772.  
  773. ================
  774. */
  775. void Draw_ConsoleBackground (int lines)
  776. {
  777.     char ver[80];
  778.     int x, i;
  779.     int y;
  780.  
  781.     y = (vid.height * 3) >> 2;
  782.     if (lines > y)
  783.         Draw_Pic(0, lines-vid.height, conback);
  784.     else
  785.         Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
  786.  
  787.     // hack the version number directly into the pic
  788. //    y = lines-186;
  789.     y = lines-14;
  790.     if (!cls.download) {
  791. #ifdef __linux__
  792.         sprintf (ver, "LinuxGL (%4.2f) QuakeWorld", LINUX_VERSION);
  793. #else
  794.         sprintf (ver, "GL (%4.2f) QuakeWorld", GLQUAKE_VERSION);
  795. #endif
  796.         x = vid.conwidth - (strlen(ver)*8 + 11) - (vid.conwidth*8/320)*7;
  797.         for (i=0 ; i<strlen(ver) ; i++)
  798.             Draw_Character (x + i * 8, y, ver[i] | 0x80);
  799.     }
  800. }
  801.  
  802.  
  803. /*
  804. =============
  805. Draw_TileClear
  806.  
  807. This repeats a 64*64 tile graphic to fill the screen around a sized down
  808. refresh window.
  809. =============
  810. */
  811. void Draw_TileClear (int x, int y, int w, int h)
  812. {
  813.     glColor3f (1,1,1);
  814.     GL_Bind (*(int *)draw_backtile->data);
  815.     glBegin (GL_QUADS);
  816.     glTexCoord2f (x/64.0, y/64.0);
  817.     glVertex2f (x, y);
  818.     glTexCoord2f ( (x+w)/64.0, y/64.0);
  819.     glVertex2f (x+w, y);
  820.     glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
  821.     glVertex2f (x+w, y+h);
  822.     glTexCoord2f ( x/64.0, (y+h)/64.0 );
  823.     glVertex2f (x, y+h);
  824.     glEnd ();
  825. }
  826.  
  827.  
  828. /*
  829. =============
  830. Draw_Fill
  831.  
  832. Fills a box of pixels with a single color
  833. =============
  834. */
  835. void Draw_Fill (int x, int y, int w, int h, int c)
  836. {
  837.     glDisable (GL_TEXTURE_2D);
  838.     glColor3f (host_basepal[c*3]/255.0,
  839.         host_basepal[c*3+1]/255.0,
  840.         host_basepal[c*3+2]/255.0);
  841.  
  842.     glBegin (GL_QUADS);
  843.  
  844.     glVertex2f (x,y);
  845.     glVertex2f (x+w, y);
  846.     glVertex2f (x+w, y+h);
  847.     glVertex2f (x, y+h);
  848.  
  849.     glEnd ();
  850.     glColor3f (1,1,1);
  851.     glEnable (GL_TEXTURE_2D);
  852. }
  853. //=============================================================================
  854.  
  855. /*
  856. ================
  857. Draw_FadeScreen
  858.  
  859. ================
  860. */
  861. void Draw_FadeScreen (void)
  862. {
  863.     glEnable (GL_BLEND);
  864.     glDisable (GL_TEXTURE_2D);
  865.     glColor4f (0, 0, 0, 0.8);
  866.     glBegin (GL_QUADS);
  867.  
  868.     glVertex2f (0,0);
  869.     glVertex2f (vid.width, 0);
  870.     glVertex2f (vid.width, vid.height);
  871.     glVertex2f (0, vid.height);
  872.  
  873.     glEnd ();
  874.     glColor4f (1,1,1,1);
  875.     glEnable (GL_TEXTURE_2D);
  876.     glDisable (GL_BLEND);
  877.  
  878.     Sbar_Changed();
  879. }
  880.  
  881. //=============================================================================
  882.  
  883. /*
  884. ================
  885. Draw_BeginDisc
  886.  
  887. Draws the little blue disc in the corner of the screen.
  888. Call before beginning any disc IO.
  889. ================
  890. */
  891. void Draw_BeginDisc (void)
  892. {
  893.     if (!draw_disc)
  894.         return;
  895.     glDrawBuffer  (GL_FRONT);
  896.     Draw_Pic (vid.width - 24, 0, draw_disc);
  897.     glDrawBuffer  (GL_BACK);
  898. }
  899.  
  900.  
  901. /*
  902. ================
  903. Draw_EndDisc
  904.  
  905. Erases the disc icon.
  906. Call after completing any disc IO
  907. ================
  908. */
  909. void Draw_EndDisc (void)
  910. {
  911. }
  912.  
  913. /*
  914. ================
  915. GL_Set2D
  916.  
  917. Setup as if the screen was 320*200
  918. ================
  919. */
  920. void GL_Set2D (void)
  921. {
  922.     glViewport (glx, gly, glwidth, glheight);
  923.  
  924.     glMatrixMode(GL_PROJECTION);
  925.     glLoadIdentity ();
  926.     glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
  927.  
  928.     glMatrixMode(GL_MODELVIEW);
  929.     glLoadIdentity ();
  930.  
  931.     glDisable (GL_DEPTH_TEST);
  932.     glDisable (GL_CULL_FACE);
  933.     glDisable (GL_BLEND);
  934.     glEnable (GL_ALPHA_TEST);
  935. //    glDisable (GL_ALPHA_TEST);
  936.  
  937.     glColor4f (1,1,1,1);
  938. }
  939.  
  940. //====================================================================
  941.  
  942. /*
  943. ================
  944. GL_FindTexture
  945. ================
  946. */
  947. int GL_FindTexture (char *identifier)
  948. {
  949.     int        i;
  950.     gltexture_t    *glt;
  951.  
  952.     for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  953.     {
  954.         if (!strcmp (identifier, glt->identifier))
  955.             return gltextures[i].texnum;
  956.     }
  957.  
  958.     return -1;
  959. }
  960.  
  961. /*
  962. ================
  963. GL_ResampleTexture
  964. ================
  965. */
  966. void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
  967. {
  968.     int        i, j;
  969.     unsigned    *inrow;
  970.     unsigned    frac, fracstep;
  971.  
  972.     fracstep = inwidth*0x10000/outwidth;
  973.     for (i=0 ; i<outheight ; i++, out += outwidth)
  974.     {
  975.         inrow = in + inwidth*(i*inheight/outheight);
  976.         frac = fracstep >> 1;
  977.         for (j=0 ; j<outwidth ; j+=4)
  978.         {
  979.             out[j] = inrow[frac>>16];
  980.             frac += fracstep;
  981.             out[j+1] = inrow[frac>>16];
  982.             frac += fracstep;
  983.             out[j+2] = inrow[frac>>16];
  984.             frac += fracstep;
  985.             out[j+3] = inrow[frac>>16];
  986.             frac += fracstep;
  987.         }
  988.     }
  989. }
  990.  
  991. /*
  992. ================
  993. GL_Resample8BitTexture -- JACK
  994. ================
  995. */
  996. void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out,  int outwidth, int outheight)
  997. {
  998.     int        i, j;
  999.     unsigned    char *inrow;
  1000.     unsigned    frac, fracstep;
  1001.  
  1002.     fracstep = inwidth*0x10000/outwidth;
  1003.     for (i=0 ; i<outheight ; i++, out += outwidth)
  1004.     {
  1005.         inrow = in + inwidth*(i*inheight/outheight);
  1006.         frac = fracstep >> 1;
  1007.         for (j=0 ; j<outwidth ; j+=4)
  1008.         {
  1009.             out[j] = inrow[frac>>16];
  1010.             frac += fracstep;
  1011.             out[j+1] = inrow[frac>>16];
  1012.             frac += fracstep;
  1013.             out[j+2] = inrow[frac>>16];
  1014.             frac += fracstep;
  1015.             out[j+3] = inrow[frac>>16];
  1016.             frac += fracstep;
  1017.         }
  1018.     }
  1019. }
  1020.  
  1021. /*
  1022. ================
  1023. GL_MipMap
  1024.  
  1025. Operates in place, quartering the size of the texture
  1026. ================
  1027. */
  1028. void GL_MipMap (byte *in, int width, int height)
  1029. {
  1030.     int        i, j;
  1031.     byte    *out;
  1032.  
  1033.     width <<=2;
  1034.     height >>= 1;
  1035.     out = in;
  1036.     for (i=0 ; i<height ; i++, in+=width)
  1037.     {
  1038.         for (j=0 ; j<width ; j+=8, out+=4, in+=8)
  1039.         {
  1040.             out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
  1041.             out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
  1042.             out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
  1043.             out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
  1044.         }
  1045.     }
  1046. }
  1047.  
  1048. /*
  1049. ================
  1050. GL_MipMap8Bit
  1051.  
  1052. Mipping for 8 bit textures
  1053. ================
  1054. */
  1055. void GL_MipMap8Bit (byte *in, int width, int height)
  1056. {
  1057.     int        i, j;
  1058.     byte    *out;
  1059.     unsigned short     r,g,b;
  1060.     byte    *at1, *at2, *at3, *at4;
  1061.  
  1062.     height >>= 1;
  1063.     out = in;
  1064.     for (i=0 ; i<height ; i++, in+=width)
  1065.         for (j=0 ; j<width ; j+=2, out+=1, in+=2)
  1066.         {
  1067.             at1 = (byte *) &d_8to24table[in[0]];
  1068.             at2 = (byte *) &d_8to24table[in[1]];
  1069.             at3 = (byte *) &d_8to24table[in[width+0]];
  1070.             at4 = (byte *) &d_8to24table[in[width+1]];
  1071.  
  1072.              r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
  1073.              g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
  1074.              b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
  1075.  
  1076.             out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
  1077.         }
  1078. }
  1079.  
  1080. /*
  1081. ===============
  1082. GL_Upload32
  1083. ===============
  1084. */
  1085. void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha)
  1086. {
  1087.     int            samples;
  1088. static    unsigned    scaled[1024*512];    // [512*256];
  1089.     int            scaled_width, scaled_height;
  1090.  
  1091.     for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
  1092.         ;
  1093.     for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
  1094.         ;
  1095.  
  1096.     scaled_width >>= (int)gl_picmip.value;
  1097.     scaled_height >>= (int)gl_picmip.value;
  1098.  
  1099.     if (scaled_width > gl_max_size.value)
  1100.         scaled_width = gl_max_size.value;
  1101.     if (scaled_height > gl_max_size.value)
  1102.         scaled_height = gl_max_size.value;
  1103.  
  1104.     if (scaled_width * scaled_height > sizeof(scaled)/4)
  1105.         Sys_Error ("GL_LoadTexture: too big");
  1106.  
  1107.     samples = alpha ? gl_alpha_format : gl_solid_format;
  1108.  
  1109. #if 0
  1110.     if (mipmap)
  1111.         gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  1112.     else if (scaled_width == width && scaled_height == height)
  1113.         glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  1114.     else
  1115.     {
  1116.         gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
  1117.             scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
  1118.         glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  1119.     }
  1120. #else
  1121. texels += scaled_width * scaled_height;
  1122.  
  1123.     if (scaled_width == width && scaled_height == height)
  1124.     {
  1125.         if (!mipmap)
  1126.         {
  1127.             glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  1128.             goto done;
  1129.         }
  1130.         memcpy (scaled, data, width*height*4);
  1131.     }
  1132.     else
  1133.         GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
  1134.  
  1135.     glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  1136.     if (mipmap)
  1137.     {
  1138.         int        miplevel;
  1139.  
  1140.         miplevel = 0;
  1141.         while (scaled_width > 1 || scaled_height > 1)
  1142.         {
  1143.             GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
  1144.             scaled_width >>= 1;
  1145.             scaled_height >>= 1;
  1146.             if (scaled_width < 1)
  1147.                 scaled_width = 1;
  1148.             if (scaled_height < 1)
  1149.                 scaled_height = 1;
  1150.             miplevel++;
  1151.             glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  1152.         }
  1153.     }
  1154. done: ;
  1155. #endif
  1156.  
  1157.  
  1158.     if (mipmap)
  1159.     {
  1160.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  1161.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1162.     }
  1163.     else
  1164.     {
  1165.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
  1166.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1167.     }
  1168. }
  1169.  
  1170. void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha) 
  1171. {
  1172.     int            i, s;
  1173.     qboolean    noalpha;
  1174.     int            samples;
  1175.     static    unsigned char scaled[1024*512];    // [512*256];
  1176.     int            scaled_width, scaled_height;
  1177.  
  1178.     s = width*height;
  1179.     // if there are no transparent pixels, make it a 3 component
  1180.     // texture even if it was specified as otherwise
  1181.     if (alpha)
  1182.     {
  1183.         noalpha = true;
  1184.         for (i=0 ; i<s ; i++)
  1185.         {
  1186.             if (data[i] == 255)
  1187.                 noalpha = false;
  1188.         }
  1189.  
  1190.         if (alpha && noalpha)
  1191.             alpha = false;
  1192.     }
  1193.     for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
  1194.         ;
  1195.     for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
  1196.         ;
  1197.  
  1198.     scaled_width >>= (int)gl_picmip.value;
  1199.     scaled_height >>= (int)gl_picmip.value;
  1200.  
  1201.     if (scaled_width > gl_max_size.value)
  1202.         scaled_width = gl_max_size.value;
  1203.     if (scaled_height > gl_max_size.value)
  1204.         scaled_height = gl_max_size.value;
  1205.  
  1206.     if (scaled_width * scaled_height > sizeof(scaled))
  1207.         Sys_Error ("GL_LoadTexture: too big");
  1208.  
  1209.     samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
  1210.  
  1211.     texels += scaled_width * scaled_height;
  1212.  
  1213.     if (scaled_width == width && scaled_height == height)
  1214.     {
  1215.         if (!mipmap)
  1216.         {
  1217.             glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
  1218.             goto done;
  1219.         }
  1220.         memcpy (scaled, data, width*height);
  1221.     }
  1222.     else
  1223.         GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
  1224.  
  1225.     glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
  1226.     if (mipmap)
  1227.     {
  1228.         int        miplevel;
  1229.  
  1230.         miplevel = 0;
  1231.         while (scaled_width > 1 || scaled_height > 1)
  1232.         {
  1233.             GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
  1234.             scaled_width >>= 1;
  1235.             scaled_height >>= 1;
  1236.             if (scaled_width < 1)
  1237.                 scaled_width = 1;
  1238.             if (scaled_height < 1)
  1239.                 scaled_height = 1;
  1240.             miplevel++;
  1241.             glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
  1242.         }
  1243.     }
  1244. done: ;
  1245.  
  1246.     if (mipmap)
  1247.     {
  1248.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  1249.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1250.     }
  1251.     else
  1252.     {
  1253.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
  1254.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1255.     }
  1256. }
  1257.  
  1258. extern qboolean VID_Is8bit();
  1259.  
  1260. /*
  1261. ===============
  1262. GL_Upload8
  1263. ===============
  1264. */
  1265. void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
  1266. {
  1267. static    unsigned    trans[640*480];        // FIXME, temporary
  1268.     int            i, s;
  1269.     qboolean    noalpha;
  1270.     int            p;
  1271.  
  1272.     s = width*height;
  1273.     // if there are no transparent pixels, make it a 3 component
  1274.     // texture even if it was specified as otherwise
  1275.     if (alpha)
  1276.     {
  1277.         noalpha = true;
  1278.         for (i=0 ; i<s ; i++)
  1279.         {
  1280.             p = data[i];
  1281.             if (p == 255)
  1282.                 noalpha = false;
  1283.             trans[i] = d_8to24table[p];
  1284.         }
  1285.  
  1286.         if (alpha && noalpha)
  1287.             alpha = false;
  1288.     }
  1289.     else
  1290.     {
  1291.         if (s&3)
  1292.             Sys_Error ("GL_Upload8: s&3");
  1293.         for (i=0 ; i<s ; i+=4)
  1294.         {
  1295.             trans[i] = d_8to24table[data[i]];
  1296.             trans[i+1] = d_8to24table[data[i+1]];
  1297.             trans[i+2] = d_8to24table[data[i+2]];
  1298.             trans[i+3] = d_8to24table[data[i+3]];
  1299.         }
  1300.     }
  1301.  
  1302.     if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
  1303.         GL_Upload8_EXT (data, width, height, mipmap, alpha);
  1304.         return;
  1305.     }
  1306.  
  1307.     GL_Upload32 (trans, width, height, mipmap, alpha);
  1308. }
  1309.  
  1310. /*
  1311. ================
  1312. GL_LoadTexture
  1313. ================
  1314. */
  1315. int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
  1316. {
  1317.     int            i;
  1318.     gltexture_t    *glt;
  1319.  
  1320.     // see if the texture is allready present
  1321.     if (identifier[0])
  1322.     {
  1323.         for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  1324.         {
  1325.             if (!strcmp (identifier, glt->identifier))
  1326.             {
  1327.                 if (width != glt->width || height != glt->height)
  1328.                     Sys_Error ("GL_LoadTexture: cache mismatch");
  1329.                 return gltextures[i].texnum;
  1330.             }
  1331.         }
  1332.     }
  1333.     else
  1334.         glt = &gltextures[numgltextures];
  1335.     numgltextures++;
  1336.  
  1337.     strcpy (glt->identifier, identifier);
  1338.     glt->texnum = texture_extension_number;
  1339.     glt->width = width;
  1340.     glt->height = height;
  1341.     glt->mipmap = mipmap;
  1342.  
  1343.     GL_Bind(texture_extension_number );
  1344.  
  1345.     GL_Upload8 (data, width, height, mipmap, alpha);
  1346.  
  1347.     texture_extension_number++;
  1348.  
  1349.     return texture_extension_number-1;
  1350. }
  1351.  
  1352. /*
  1353. ================
  1354. GL_LoadPicTexture
  1355. ================
  1356. */
  1357. int GL_LoadPicTexture (qpic_t *pic)
  1358. {
  1359.     return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
  1360. }
  1361.  
  1362. /****************************************/
  1363.  
  1364. static GLenum oldtarget = TEXTURE0_SGIS;
  1365.  
  1366. void GL_SelectTexture (GLenum target) 
  1367. {
  1368.     if (!gl_mtexable)
  1369.         return;
  1370. #ifndef __linux__ // no multitexture under Linux yet
  1371.     qglSelectTextureSGIS(target);
  1372. #endif
  1373.     if (target == oldtarget) 
  1374.         return;
  1375.     cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
  1376.     currenttexture = cnttextures[target-TEXTURE0_SGIS];
  1377.     oldtarget = target;
  1378. }
  1379.