home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / gl_draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  30.7 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.