2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
21 // draw.c -- this is the only file outside the refresh that touches the
26 #define GL_COLOR_INDEX8_EXT 0x80E5
28 extern unsigned char d_15to8table[65536];
30 cvar_t qsg_version = {"qsg_version", "1"};
31 cvar_t gl_max_size = {"gl_max_size", "1024"};
32 cvar_t gl_picmip = {"gl_picmip", "0"};
33 cvar_t gl_conalpha = {"gl_conalpha", "1"};
34 cvar_t gl_lerpimages = {"gl_lerpimages", "1"};
36 byte *draw_chars; // 8*8 graphic characters
39 int translate_texture;
48 byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
49 qpic_t *conback = (qpic_t *)&conback_buffer;
51 int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
52 int gl_filter_max = GL_LINEAR;
63 // LordHavoc: 32bit textures
65 // LordHavoc: CRC to identify cache mismatchs
67 int lerped; // whether this texture was uploaded with or without interpolation
70 #define MAX_GLTEXTURES 4096
71 gltexture_t gltextures[MAX_GLTEXTURES];
75 =============================================================================
79 Allocate all the little status bar obejcts into a single texture
80 to crutch up stupid hardware / drivers
82 =============================================================================
86 #define BLOCK_WIDTH 256
87 #define BLOCK_HEIGHT 256
89 int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
90 byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
94 // returns a texture number and the position inside it
95 int Scrap_AllocBlock (int w, int h, int *x, int *y)
101 for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
105 for (i=0 ; i<BLOCK_WIDTH-w ; i++)
109 for (j=0 ; j<w ; j++)
111 if (scrap_allocated[texnum][i+j] >= best)
113 if (scrap_allocated[texnum][i+j] > best2)
114 best2 = scrap_allocated[texnum][i+j];
117 { // this is a valid spot
123 if (best + h > BLOCK_HEIGHT)
126 for (i=0 ; i<w ; i++)
127 scrap_allocated[texnum][*x + i] = best + h;
132 Sys_Error ("Scrap_AllocBlock: full");
138 void Scrap_Upload (void)
144 for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
146 glBindTexture(GL_TEXTURE_2D, scrap_texnum + texnum);
147 GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
152 //=============================================================================
153 /* Support Routines */
155 typedef struct cachepic_s
157 char name[MAX_QPATH];
159 byte padding[32]; // for appended glpic
162 #define MAX_CACHED_PICS 128
163 cachepic_t menu_cachepics[MAX_CACHED_PICS];
164 int menu_numcachepics;
166 byte menuplyr_pixels[4096];
171 int GL_LoadPicTexture (qpic_t *pic);
173 qpic_t *Draw_PicFromWad (char *name)
178 p = W_GetLumpName (name);
179 gl = (glpic_t *)p->data;
181 // load little ones into the scrap
182 if (p->width < 64 && p->height < 64)
188 texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
191 for (i=0 ; i<p->height ; i++)
192 for (j=0 ; j<p->width ; j++, k++)
193 scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
194 texnum += scrap_texnum;
196 gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
197 gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
198 gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
199 gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
202 pic_texels += p->width*p->height;
203 // LordHavoc: LINEAR interpolation
204 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
205 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
209 gl->texnum = GL_LoadPicTexture (p);
214 // LordHavoc: LINEAR interpolation
215 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //NEAREST);
216 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //NEAREST);
227 qpic_t *Draw_CachePic (char *path)
234 for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
235 if (!strcmp (path, pic->name))
238 if (menu_numcachepics == MAX_CACHED_PICS)
239 Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
241 strcpy (pic->name, path);
244 // load the pic from disk
246 dat = (qpic_t *)COM_LoadTempFile (path, false);
248 Sys_Error ("Draw_CachePic: failed to load %s", path);
251 // HACK HACK HACK --- we need to keep the bytes for
252 // the translatable player picture just for the menu
253 // configuration dialog
254 if (!strcmp (path, "gfx/menuplyr.lmp"))
255 memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
257 pic->pic.width = dat->width;
258 pic->pic.height = dat->height;
260 gl = (glpic_t *)pic->pic.data;
261 gl->texnum = GL_LoadPicTexture (dat);
271 void Draw_CharToConback (int num, byte *dest)
280 source = draw_chars + (row<<10) + (col<<3);
286 for (x=0 ; x<8 ; x++)
287 if (source[x] != 255)
288 dest[x] = 0x60 + source[x];
298 int minimize, maximize;
302 {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
303 {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
304 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
305 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
306 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
307 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
315 void Draw_TextureMode_f (void)
322 for (i=0 ; i< 6 ; i++)
323 if (gl_filter_min == modes[i].minimize)
325 Con_Printf ("%s\n", modes[i].name);
328 Con_Printf ("current filter is unknown???\n");
332 for (i=0 ; i< 6 ; i++)
334 if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
339 Con_Printf ("bad filter name\n");
343 gl_filter_min = modes[i].minimize;
344 gl_filter_max = modes[i].maximize;
346 // change all the existing mipmap texture objects
347 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
351 glBindTexture(GL_TEXTURE_2D, glt->texnum);
352 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
353 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
358 extern void LoadSky_f(void);
360 extern char *QSG_EXTENSIONS;
367 void rmain_registercvars();
368 extern int buildnumber;
369 void Draw_Init (void)
379 Cvar_RegisterVariable (&qsg_version);
380 Cvar_RegisterVariable (&gl_max_size);
381 Cvar_RegisterVariable (&gl_picmip);
382 Cvar_RegisterVariable (&gl_conalpha);
383 Cvar_RegisterVariable (&gl_lerpimages);
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");
390 Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
392 Cmd_AddCommand ("loadsky", &LoadSky_f);
394 // load the console background and the charset
395 // by hand, because we need to write the version
396 // string into the background before turning
398 draw_chars = W_GetLumpName ("conchars");
399 for (i=0 ; i<256*64 ; i++)
400 if (draw_chars[i] == 0)
401 draw_chars[i] = 255; // proper transparent color
403 // now turn them into textures
404 char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
406 start = Hunk_LowMark();
408 cb = (qpic_t *)COM_LoadMallocFile ("gfx/conback.lmp", false);
410 Sys_Error ("Couldn't load gfx/conback.lmp");
413 // hack the version number directly into the pic
415 #if defined(__linux__)
416 sprintf (ver, "DPNehahra Linux GL %.2f build %5i", (float) VERSION, buildnumber);
418 sprintf (ver, "DPNehahra Windows GL %.2f build %5i", (float) VERSION, buildnumber);
420 sprintf (ver, "DPNehahra Unknown GL %.2f build %5i", (float) VERSION, buildnumber);
423 #if defined(__linux__)
424 sprintf (ver, "DarkPlaces Linux GL %.2f build %5i", (float) VERSION, buildnumber);
426 sprintf (ver, "DarkPlaces Windows GL %.2f build %5i", (float) VERSION, buildnumber);
428 sprintf (ver, "DarkPlaces Unknown GL %.2f build %5i", (float) VERSION, buildnumber);
431 dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
433 for (x=0 ; x<y ; x++)
434 Draw_CharToConback (ver[x], dest+(x<<3));
436 gl = (glpic_t *)conback->data;
437 gl->texnum = GL_LoadTexture ("conback", cb->width, cb->height, cb->data, false, false, 1);
442 conback->width = vid.width;
443 conback->height = vid.height;
445 // free loaded console
448 // save a texture slot for translated picture
449 translate_texture = texture_extension_number++;
451 // save slots for scraps
452 scrap_texnum = texture_extension_number;
453 texture_extension_number += MAX_SCRAPS;
456 // get the other pics we need
458 draw_disc = Draw_PicFromWad ("disc");
460 rmain_registercvars();
468 Draws one 8*8 graphics character with 0 being transparent.
469 It can be clipped to the top of the screen to allow the console to be
470 smoothly scrolled off.
473 void Draw_Character (int x, int y, int num)
476 float frow, fcol, size;
484 return; // totally off screen
493 glBindTexture(GL_TEXTURE_2D, char_texture);
494 // LordHavoc: NEAREST mode on text if not scaling up
495 if ((int) vid.width < glwidth)
497 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
498 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
503 glTexCoord2f (fcol, frow);
505 glTexCoord2f (fcol + size, frow);
507 glTexCoord2f (fcol + size, frow + size);
508 glVertex2f (x+8, y+8);
509 glTexCoord2f (fcol, frow + size);
513 // LordHavoc: revert to LINEAR mode
514 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
515 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
523 // LordHavoc: sped this up a lot, and added maxlen
524 void Draw_String (int x, int y, char *str, int maxlen)
528 if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print
531 maxlen = strlen(str);
532 else if (maxlen > (int) strlen(str))
533 maxlen = strlen(str);
534 glBindTexture(GL_TEXTURE_2D, char_texture);
536 // LordHavoc: NEAREST mode on text if not scaling up
537 if ((int) vid.width < glwidth)
539 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
540 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
545 while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room
547 if ((num = *str++) != 32) // skip spaces
549 frow = (float) ((int) num >> 4)*0.0625;
550 fcol = (float) ((int) num & 15)*0.0625;
551 glTexCoord2f (fcol, frow);
553 glTexCoord2f (fcol + 0.0625, frow);
555 glTexCoord2f (fcol + 0.0625, frow + 0.0625);
556 glVertex2f (x+8, y+8);
557 glTexCoord2f (fcol, frow + 0.0625);
564 // LordHavoc: revert to LINEAR mode
565 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
566 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
574 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
580 gl = (glpic_t *)pic->data;
581 // glDisable(GL_ALPHA_TEST);
582 // glEnable (GL_BLEND);
583 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
584 // glCullFace(GL_FRONT);
585 glColor4f(0.8,0.8,0.8,alpha);
586 glBindTexture(GL_TEXTURE_2D, gl->texnum);
587 // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
589 glTexCoord2f (gl->sl, gl->tl);
591 glTexCoord2f (gl->sh, gl->tl);
592 glVertex2f (x+pic->width, y);
593 glTexCoord2f (gl->sh, gl->th);
594 glVertex2f (x+pic->width, y+pic->height);
595 glTexCoord2f (gl->sl, gl->th);
596 glVertex2f (x, y+pic->height);
599 // glEnable(GL_ALPHA_TEST);
600 // glDisable (GL_BLEND);
609 void Draw_Pic (int x, int y, qpic_t *pic)
615 gl = (glpic_t *)pic->data;
616 glColor3f(0.8,0.8,0.8);
617 glBindTexture(GL_TEXTURE_2D, gl->texnum);
619 glTexCoord2f (gl->sl, gl->tl);
621 glTexCoord2f (gl->sh, gl->tl);
622 glVertex2f (x+pic->width, y);
623 glTexCoord2f (gl->sh, gl->th);
624 glVertex2f (x+pic->width, y+pic->height);
625 glTexCoord2f (gl->sl, gl->th);
626 glVertex2f (x, y+pic->height);
636 void Draw_TransPic (int x, int y, qpic_t *pic)
638 if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || (unsigned)(y + pic->height) > vid.height)
639 Sys_Error ("Draw_TransPic: bad coordinates");
641 // glEnable(GL_BLEND);
642 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
643 // glDisable(GL_ALPHA_TEST);
644 Draw_Pic (x, y, pic);
645 // glDisable(GL_BLEND);
651 Draw_TransPicTranslate
653 Only used for the player color selection menu
656 void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
659 unsigned trans[64*64], *dest;
663 glBindTexture(GL_TEXTURE_2D, translate_texture);
665 c = pic->width * pic->height;
668 for (v=0 ; v<64 ; v++, dest += 64)
670 src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
671 for (u=0 ; u<64 ; u++)
673 p = src[(u*pic->width)>>6];
677 dest[u] = d_8to24table[translation[p]];
681 glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
683 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
684 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
686 glColor3f(0.8,0.8,0.8);
691 glVertex2f (x+pic->width, y);
693 glVertex2f (x+pic->width, y+pic->height);
695 glVertex2f (x, y+pic->height);
702 Draw_ConsoleBackground
706 void Draw_ConsoleBackground (int lines)
708 // LordHavoc: changed alpha
709 //int y = (vid.height >> 1);
711 if (lines >= (int) vid.height)
712 Draw_Pic(0, lines - vid.height, conback);
714 Draw_AlphaPic (0, lines - vid.height, conback, gl_conalpha.value*lines/vid.height);
715 // Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
722 Fills a box of pixels with a single color
725 void Draw_Fill (int x, int y, int w, int h, int c)
727 glDisable (GL_TEXTURE_2D);
728 glColor3f (host_basepal[c*3]/255.0, host_basepal[c*3+1]/255.0, host_basepal[c*3+2]/255.0);
734 glVertex2f (x+w, y+h);
739 glEnable (GL_TEXTURE_2D);
741 //=============================================================================
743 //=============================================================================
749 Setup as if the screen was 320*200
754 glViewport (glx, gly, glwidth, glheight);
756 glMatrixMode(GL_PROJECTION);
758 glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
760 glMatrixMode(GL_MODELVIEW);
763 glDisable (GL_DEPTH_TEST);
764 glDisable (GL_CULL_FACE);
765 glEnable (GL_BLEND); // was Disable
766 // glEnable (GL_ALPHA_TEST);
767 glDisable (GL_ALPHA_TEST);
768 glEnable(GL_TEXTURE_2D);
770 // LordHavoc: added this
771 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
772 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
777 // LordHavoc: SHOWLMP stuff
778 #define SHOWLMP_MAXLABELS 256
779 typedef struct showlmp_s
788 showlmp_t showlmp[SHOWLMP_MAXLABELS];
790 void SHOWLMP_decodehide()
794 lmplabel = MSG_ReadString();
795 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
796 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
798 showlmp[i].isactive = false;
803 void SHOWLMP_decodeshow()
806 byte lmplabel[256], picname[256];
808 strcpy(lmplabel,MSG_ReadString());
809 strcpy(picname, MSG_ReadString());
813 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
814 if (showlmp[i].isactive)
816 if (strcmp(showlmp[i].label, lmplabel) == 0)
819 break; // drop out to replace it
822 else if (k < 0) // find first empty one to replace
825 return; // none found to replace
826 // change existing one
827 showlmp[k].isactive = true;
828 strcpy(showlmp[k].label, lmplabel);
829 strcpy(showlmp[k].pic, picname);
834 void SHOWLMP_drawall()
837 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
838 if (showlmp[i].isactive)
839 Draw_TransPic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic));
845 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
846 showlmp[i].isactive = false;
849 //====================================================================
856 int GL_FindTexture (char *identifier)
861 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
863 if (!strcmp (identifier, glt->identifier))
864 return gltextures[i].texnum;
870 extern byte qgamma[];
872 // LordHavoc: gamma correction and improved resampling
873 void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
876 float f, fstep, l1, l2;
877 fstep = (float) inwidth/outwidth;
878 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
883 in += (xi - oldx) * 4;
886 if (xi < (inwidth-1))
890 *out++ = qgamma[(byte) (in[0] * l1 + in[4] * l2)];
891 *out++ = qgamma[(byte) (in[1] * l1 + in[5] * l2)];
892 *out++ = qgamma[(byte) (in[2] * l1 + in[6] * l2)];
893 *out++ = (byte) (in[3] * l1 + in[7] * l2) ;
895 else // last pixel of the line has no pixel to lerp to
897 *out++ = qgamma[in[0]];
898 *out++ = qgamma[in[1]];
899 *out++ = qgamma[in[2]];
910 void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
912 // LordHavoc: gamma correction and greatly improved resampling
913 if (gl_lerpimages.value)
916 byte *inrow, *out, *row1, *row2;
917 float f, fstep, l1, l2;
919 fstep = (float) inheight/outheight;
921 row1 = malloc(outwidth*4);
922 row2 = malloc(outwidth*4);
925 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
926 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
927 for (i = 0, f = 0;i < outheight;i++,f += fstep)
932 inrow = (byte *)((int)indata + inwidth*4*yi);
934 memcpy(row1, row2, outwidth*4);
936 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
937 if (yi < (inheight-1))
938 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
940 memcpy(row2, row1, outwidth*4);
943 if (yi < (inheight-1))
947 for (j = 0;j < outwidth;j++)
949 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
950 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
951 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
952 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
957 else // last line has no pixels to lerp to
959 for (j = 0;j < outwidth;j++)
975 unsigned frac, fracstep;
976 byte *inrow, *out, *inpix;
979 fracstep = inwidth*0x10000/outwidth;
980 for (i=0 ; i<outheight ; i++)
982 inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
983 frac = fracstep >> 1;
984 for (j=0 ; j<outwidth ; j+=4)
986 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
987 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
988 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
989 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
997 GL_Resample8BitTexture -- JACK
1000 void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
1003 unsigned char *inrow;
1004 unsigned frac, fracstep;
1006 fracstep = inwidth*0x10000/outwidth;
1007 for (i=0 ; i<outheight ; i++, out += outwidth)
1009 inrow = in + inwidth*(i*inheight/outheight);
1010 frac = fracstep >> 1;
1011 for (j=0 ; j<outwidth ; j+=4)
1013 out[j] = inrow[frac>>16];
1015 out[j+1] = inrow[frac>>16];
1017 out[j+2] = inrow[frac>>16];
1019 out[j+3] = inrow[frac>>16];
1030 Operates in place, quartering the size of the texture
1033 void GL_MipMap (byte *in, int width, int height)
1041 for (i=0 ; i<height ; i++, in+=width)
1043 for (j=0 ; j<width ; j+=8, out+=4, in+=8)
1045 out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
1046 out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
1047 out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
1048 out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
1057 Mipping for 8 bit textures
1060 void GL_MipMap8Bit (byte *in, int width, int height)
1063 unsigned short r,g,b;
1064 byte *out, *at1, *at2, *at3, *at4;
1068 for (i=0 ; i<height ; i++, in+=width)
1070 for (j=0 ; j<width ; j+=2, out+=1, in+=2)
1072 at1 = (byte *) (d_8to24table + in[0]);
1073 at2 = (byte *) (d_8to24table + in[1]);
1074 at3 = (byte *) (d_8to24table + in[width+0]);
1075 at4 = (byte *) (d_8to24table + in[width+1]);
1077 r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
1078 g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
1079 b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
1081 out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
1091 void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha)
1093 int samples, scaled_width, scaled_height, i;
1094 byte *in, *out, *scaled;
1096 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1098 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1101 scaled_width >>= (int)gl_picmip.value;
1102 scaled_height >>= (int)gl_picmip.value;
1104 if (scaled_width > gl_max_size.value)
1105 scaled_width = gl_max_size.value;
1106 if (scaled_height > gl_max_size.value)
1107 scaled_height = gl_max_size.value;
1113 for (i = 3;i < width*height*4;i += 4)
1121 samples = alpha ? gl_alpha_format : gl_solid_format;
1125 gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1126 else if (scaled_width == width && scaled_height == height)
1127 glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1130 gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, scaled, scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
1131 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1134 texels += scaled_width * scaled_height;
1136 scaled = malloc(scaled_width*scaled_height*4);
1137 if (scaled_width == width && scaled_height == height)
1139 // LordHavoc: gamma correct while copying
1141 out = (byte *)scaled;
1142 for (i = 0;i < width*height;i++)
1144 *out++ = qgamma[*in++];
1145 *out++ = qgamma[*in++];
1146 *out++ = qgamma[*in++];
1151 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
1153 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1159 while (scaled_width > 1 || scaled_height > 1)
1161 GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
1163 scaled_height >>= 1;
1164 if (scaled_width < 1)
1166 if (scaled_height < 1)
1169 glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1177 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1178 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1182 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1183 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1188 void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap)
1190 int scaled_width, scaled_height;
1191 byte *scaled = NULL;
1193 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1195 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1198 scaled_width >>= (int)gl_picmip.value;
1199 scaled_height >>= (int)gl_picmip.value;
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;
1206 texels += scaled_width * scaled_height;
1208 if (scaled_width == width && scaled_height == height)
1212 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
1215 scaled = malloc(scaled_width*scaled_height*4);
1216 memcpy (scaled, data, width*height);
1220 scaled = malloc(scaled_width*scaled_height*4);
1221 GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
1224 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1230 while (scaled_width > 1 || scaled_height > 1)
1232 GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
1234 scaled_height >>= 1;
1235 if (scaled_width < 1)
1237 if (scaled_height < 1)
1240 glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1248 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1249 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1253 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1254 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1259 qboolean VID_Is8bit();
1266 void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
1268 static unsigned *trans;
1276 trans = malloc(s*4);
1277 // if there are no transparent pixels, make it a 3 component
1278 // texture even if it was specified as otherwise
1282 for (i=0 ; i<s ; i++)
1286 trans[i] = d_8to24table[p];
1289 trans[i] = 0; // force to black
1296 if (VID_Is8bit() && (data!=scrap_texels[0]))
1298 GL_Upload8_EXT (data, width, height, mipmap);
1307 // LordHavoc: dodge the copy if it will be uploaded as 8bit
1308 if (VID_Is8bit() && (data!=scrap_texels[0]))
1310 GL_Upload8_EXT (data, width, height, mipmap);
1315 // Sys_Error ("GL_Upload8: s&3");
1319 *outdata++ = d_8to24table[*indata++];
1322 *outdata++ = d_8to24table[*indata++];
1323 *outdata++ = d_8to24table[*indata++];
1325 for (i = 0;i < s;i+=4)
1327 *outdata++ = d_8to24table[*indata++];
1328 *outdata++ = d_8to24table[*indata++];
1329 *outdata++ = d_8to24table[*indata++];
1330 *outdata++ = d_8to24table[*indata++];
1334 GL_Upload32 (trans, width, height, mipmap, alpha);
1343 int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
1352 // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
1353 crc = CRC_Block(data, width*height*bytesperpixel);
1354 // see if the texture is already present
1357 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
1359 if (!strcmp (identifier, glt->identifier))
1361 // LordHavoc: everyone hates cache mismatchs, so I fixed it
1362 if (crc != glt->crc || width != glt->width || height != glt->height)
1364 Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
1365 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
1366 //Sys_Error ("GL_LoadTexture: cache mismatch");
1368 if ((gl_lerpimages.value != 0) != glt->lerped)
1369 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
1374 // LordHavoc: although this could be an else condition as it was in the original id code,
1375 // it is more clear this way
1376 // LordHavoc: check if there are still slots available
1377 if (numgltextures >= MAX_GLTEXTURES)
1378 Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
1379 glt = &gltextures[numgltextures++];
1381 strcpy (glt->identifier, identifier);
1382 glt->texnum = texture_extension_number;
1383 texture_extension_number++;
1384 // LordHavoc: label to drop out of the loop into the setup code
1385 GL_LoadTexture_setup:
1386 glt->crc = crc; // LordHavoc: used to verify textures are identical
1388 glt->height = height;
1389 glt->mipmap = mipmap;
1390 glt->bytesperpixel = bytesperpixel;
1391 glt->lerped = gl_lerpimages.value != 0;
1393 glBindTexture(GL_TEXTURE_2D, glt->texnum);
1395 if (bytesperpixel == 1) // 8bit
1396 GL_Upload8 (data, width, height, mipmap, alpha);
1398 GL_Upload32 (data, width, height, mipmap, true);
1399 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1409 int GL_LoadPicTexture (qpic_t *pic)
1411 return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
1414 int GL_GetTextureSlots (int count)
1416 gltexture_t *glt, *first;
1418 first = glt = &gltextures[numgltextures];
1421 glt->identifier[0] = 0;
1422 glt->texnum = texture_extension_number++;
1426 glt->bytesperpixel = 0;
1430 return first->texnum;