Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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