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_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");
137 void Scrap_Upload (void)
143 for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
145 glBindTexture(GL_TEXTURE_2D, scrap_texnum + texnum);
146 GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
151 //=============================================================================
152 /* Support Routines */
154 typedef struct cachepic_s
156 char name[MAX_QPATH];
158 byte padding[32]; // for appended glpic
161 #define MAX_CACHED_PICS 128
162 cachepic_t menu_cachepics[MAX_CACHED_PICS];
163 int menu_numcachepics;
165 byte menuplyr_pixels[4096];
170 int GL_LoadPicTexture (qpic_t *pic);
172 qpic_t *Draw_PicFromWad (char *name)
177 p = W_GetLumpName (name);
178 gl = (glpic_t *)p->data;
180 // load little ones into the scrap
181 if (p->width < 64 && p->height < 64)
187 texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
190 for (i=0 ; i<p->height ; i++)
191 for (j=0 ; j<p->width ; j++, k++)
192 scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
193 texnum += scrap_texnum;
195 gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
196 gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
197 gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
198 gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
201 pic_texels += p->width*p->height;
202 // LordHavoc: LINEAR interpolation
203 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
204 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
208 gl->texnum = GL_LoadPicTexture (p);
213 // LordHavoc: LINEAR interpolation
214 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //NEAREST);
215 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //NEAREST);
226 qpic_t *Draw_CachePic (char *path)
233 for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
234 if (!strcmp (path, pic->name))
237 if (menu_numcachepics == MAX_CACHED_PICS)
238 Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
240 strcpy (pic->name, path);
243 // load the pic from disk
245 dat = (qpic_t *)COM_LoadTempFile (path, false);
247 Sys_Error ("Draw_CachePic: failed to load %s", path);
250 // HACK HACK HACK --- we need to keep the bytes for
251 // the translatable player picture just for the menu
252 // configuration dialog
253 if (!strcmp (path, "gfx/menuplyr.lmp"))
254 memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
256 pic->pic.width = dat->width;
257 pic->pic.height = dat->height;
259 gl = (glpic_t *)pic->pic.data;
260 gl->texnum = GL_LoadPicTexture (dat);
270 void Draw_CharToConback (int num, byte *dest)
279 source = draw_chars + (row<<10) + (col<<3);
285 for (x=0 ; x<8 ; x++)
286 if (source[x] != 255)
287 dest[x] = 0x60 + source[x];
297 int minimize, maximize;
301 {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
302 {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
303 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
304 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
305 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
306 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
314 void Draw_TextureMode_f (void)
321 for (i=0 ; i< 6 ; i++)
322 if (gl_filter_min == modes[i].minimize)
324 Con_Printf ("%s\n", modes[i].name);
327 Con_Printf ("current filter is unknown???\n");
331 for (i=0 ; i< 6 ; i++)
333 if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
338 Con_Printf ("bad filter name\n");
342 gl_filter_min = modes[i].minimize;
343 gl_filter_max = modes[i].maximize;
345 // change all the existing mipmap texture objects
346 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
350 glBindTexture(GL_TEXTURE_2D, glt->texnum);
351 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
352 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
357 extern void LoadSky_f(void);
359 extern char *QSG_EXTENSIONS;
366 void rmain_registercvars();
367 void Draw_Init (void)
377 Cvar_RegisterVariable (&qsg_version);
378 Cvar_RegisterVariable (&gl_max_size);
379 Cvar_RegisterVariable (&gl_picmip);
380 Cvar_RegisterVariable (&gl_conalpha);
381 Cvar_RegisterVariable (&gl_lerpimages);
383 // 3dfx can only handle 256 wide textures
384 if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
385 strstr((char *)gl_renderer, "Glide"))
386 Cvar_Set ("gl_max_size", "256");
388 Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
390 Cmd_AddCommand ("loadsky", &LoadSky_f);
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
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
401 // now turn them into textures
402 char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
404 start = Hunk_LowMark();
406 cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp", false);
408 Sys_Error ("Couldn't load gfx/conback.lmp");
411 // hack the version number directly into the pic
413 #if defined(__linux__)
414 sprintf (ver, "(DPNehahra %.2f, Linux %2.2f, gl %.2f) %.2f", (float) DP_VERSION, (float)LINUX_VERSION, (float)GLQUAKE_VERSION, (float)VERSION);
416 sprintf (ver, "(DPNehahra %.2f, gl %.2f) %.2f", (float) DP_VERSION, (float)GLQUAKE_VERSION, (float)VERSION);
419 #if defined(__linux__)
420 sprintf (ver, "(DarkPlaces %.2f, Linux %2.2f, gl %.2f) %.2f", (float) DP_VERSION, (float)LINUX_VERSION, (float)GLQUAKE_VERSION, (float)VERSION);
422 sprintf (ver, "(DarkPlaces %.2f, gl %.2f) %.2f", (float) DP_VERSION, (float)GLQUAKE_VERSION, (float)VERSION);
425 dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
427 for (x=0 ; x<y ; x++)
428 Draw_CharToConback (ver[x], dest+(x<<3));
430 gl = (glpic_t *)conback->data;
431 gl->texnum = GL_LoadTexture ("conback", cb->width, cb->height, cb->data, false, false, 1);
436 conback->width = vid.width;
437 conback->height = vid.height;
439 // free loaded console
440 Hunk_FreeToLowMark(start);
442 // save a texture slot for translated picture
443 translate_texture = texture_extension_number++;
445 // save slots for scraps
446 scrap_texnum = texture_extension_number;
447 texture_extension_number += MAX_SCRAPS;
450 // get the other pics we need
452 draw_disc = Draw_PicFromWad ("disc");
454 rmain_registercvars();
462 Draws one 8*8 graphics character with 0 being transparent.
463 It can be clipped to the top of the screen to allow the console to be
464 smoothly scrolled off.
467 void Draw_Character (int x, int y, int num)
470 float frow, fcol, size;
478 return; // totally off screen
487 glBindTexture(GL_TEXTURE_2D, char_texture);
488 // LordHavoc: NEAREST mode on text if not scaling up
489 if ((int) vid.width < glwidth)
491 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
492 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
497 glTexCoord2f (fcol, frow);
499 glTexCoord2f (fcol + size, frow);
501 glTexCoord2f (fcol + size, frow + size);
502 glVertex2f (x+8, y+8);
503 glTexCoord2f (fcol, frow + size);
507 // LordHavoc: revert to LINEAR mode
508 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
509 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
517 // LordHavoc: sped this up a lot, and added maxlen
518 void Draw_String (int x, int y, char *str, int maxlen)
522 if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print
525 maxlen = strlen(str);
526 else if (maxlen > (int) strlen(str))
527 maxlen = strlen(str);
528 glBindTexture(GL_TEXTURE_2D, char_texture);
530 // LordHavoc: NEAREST mode on text if not scaling up
531 if ((int) vid.width < glwidth)
533 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
534 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
539 while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room
541 if ((num = *str++) != 32) // skip spaces
543 frow = (float) ((int) num >> 4)*0.0625;
544 fcol = (float) ((int) num & 15)*0.0625;
545 glTexCoord2f (fcol, frow);
547 glTexCoord2f (fcol + 0.0625, frow);
549 glTexCoord2f (fcol + 0.0625, frow + 0.0625);
550 glVertex2f (x+8, y+8);
551 glTexCoord2f (fcol, frow + 0.0625);
558 // LordHavoc: revert to LINEAR mode
559 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
560 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
568 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
574 gl = (glpic_t *)pic->data;
575 // glDisable(GL_ALPHA_TEST);
576 // glEnable (GL_BLEND);
577 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
578 // glCullFace(GL_FRONT);
579 glColor4f(0.8,0.8,0.8,alpha);
580 glBindTexture(GL_TEXTURE_2D, gl->texnum);
581 // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
583 glTexCoord2f (gl->sl, gl->tl);
585 glTexCoord2f (gl->sh, gl->tl);
586 glVertex2f (x+pic->width, y);
587 glTexCoord2f (gl->sh, gl->th);
588 glVertex2f (x+pic->width, y+pic->height);
589 glTexCoord2f (gl->sl, gl->th);
590 glVertex2f (x, y+pic->height);
593 // glEnable(GL_ALPHA_TEST);
594 // glDisable (GL_BLEND);
603 void Draw_Pic (int x, int y, qpic_t *pic)
609 gl = (glpic_t *)pic->data;
610 glColor3f(0.8,0.8,0.8);
611 glBindTexture(GL_TEXTURE_2D, gl->texnum);
613 glTexCoord2f (gl->sl, gl->tl);
615 glTexCoord2f (gl->sh, gl->tl);
616 glVertex2f (x+pic->width, y);
617 glTexCoord2f (gl->sh, gl->th);
618 glVertex2f (x+pic->width, y+pic->height);
619 glTexCoord2f (gl->sl, gl->th);
620 glVertex2f (x, y+pic->height);
630 void Draw_TransPic (int x, int y, qpic_t *pic)
632 if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || (unsigned)(y + pic->height) > vid.height)
633 Sys_Error ("Draw_TransPic: bad coordinates");
635 // glEnable(GL_BLEND);
636 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
637 // glDisable(GL_ALPHA_TEST);
638 Draw_Pic (x, y, pic);
639 // glDisable(GL_BLEND);
645 Draw_TransPicTranslate
647 Only used for the player color selection menu
650 void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
653 unsigned trans[64*64], *dest;
657 glBindTexture(GL_TEXTURE_2D, translate_texture);
659 c = pic->width * pic->height;
662 for (v=0 ; v<64 ; v++, dest += 64)
664 src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
665 for (u=0 ; u<64 ; u++)
667 p = src[(u*pic->width)>>6];
671 dest[u] = d_8to24table[translation[p]];
675 glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
677 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
678 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
680 glColor3f(0.8,0.8,0.8);
685 glVertex2f (x+pic->width, y);
687 glVertex2f (x+pic->width, y+pic->height);
689 glVertex2f (x, y+pic->height);
696 Draw_ConsoleBackground
700 void Draw_ConsoleBackground (int lines)
702 // LordHavoc: changed alpha
703 //int y = (vid.height >> 1);
705 if (lines >= (int) vid.height)
706 Draw_Pic(0, lines - vid.height, conback);
708 Draw_AlphaPic (0, lines - vid.height, conback, gl_conalpha.value*lines/vid.height);
709 // Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
716 Fills a box of pixels with a single color
719 void Draw_Fill (int x, int y, int w, int h, int c)
721 glDisable (GL_TEXTURE_2D);
722 glColor3f (host_basepal[c*3]/255.0, host_basepal[c*3+1]/255.0, host_basepal[c*3+2]/255.0);
728 glVertex2f (x+w, y+h);
733 glEnable (GL_TEXTURE_2D);
735 //=============================================================================
737 //=============================================================================
743 Setup as if the screen was 320*200
748 glViewport (glx, gly, glwidth, glheight);
750 glMatrixMode(GL_PROJECTION);
752 glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
754 glMatrixMode(GL_MODELVIEW);
757 glDisable (GL_DEPTH_TEST);
758 glDisable (GL_CULL_FACE);
759 glEnable (GL_BLEND); // was Disable
760 // glEnable (GL_ALPHA_TEST);
761 glDisable (GL_ALPHA_TEST);
762 glEnable(GL_TEXTURE_2D);
764 // LordHavoc: added this
765 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
766 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
771 // LordHavoc: SHOWLMP stuff
772 #define SHOWLMP_MAXLABELS 256
773 typedef struct showlmp_s
782 showlmp_t showlmp[SHOWLMP_MAXLABELS];
784 void SHOWLMP_decodehide()
788 lmplabel = MSG_ReadString();
789 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
790 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
792 showlmp[i].isactive = false;
797 void SHOWLMP_decodeshow()
800 byte lmplabel[256], picname[256];
802 strcpy(lmplabel,MSG_ReadString());
803 strcpy(picname, MSG_ReadString());
807 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
808 if (showlmp[i].isactive)
810 if (strcmp(showlmp[i].label, lmplabel) == 0)
813 break; // drop out to replace it
816 else if (k < 0) // find first empty one to replace
819 return; // none found to replace
820 // change existing one
821 showlmp[k].isactive = true;
822 strcpy(showlmp[k].label, lmplabel);
823 strcpy(showlmp[k].pic, picname);
828 void SHOWLMP_drawall()
831 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
832 if (showlmp[i].isactive)
833 Draw_TransPic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic));
839 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
840 showlmp[i].isactive = false;
843 //====================================================================
850 int GL_FindTexture (char *identifier)
855 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
857 if (!strcmp (identifier, glt->identifier))
858 return gltextures[i].texnum;
866 // LordHavoc: gamma correction and improved resampling
867 void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
870 float f, fstep, l1, l2;
871 fstep = (float) inwidth/outwidth;
872 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
877 in += (xi - oldx) * 4;
880 if (xi < (inwidth-1))
884 *out++ = gamma[(byte) (in[0] * l1 + in[4] * l2)];
885 *out++ = gamma[(byte) (in[1] * l1 + in[5] * l2)];
886 *out++ = gamma[(byte) (in[2] * l1 + in[6] * l2)];
887 *out++ = (byte) (in[3] * l1 + in[7] * l2) ;
889 else // last pixel of the line has no pixel to lerp to
891 *out++ = gamma[in[0]];
892 *out++ = gamma[in[1]];
893 *out++ = gamma[in[2]];
904 void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
906 // LordHavoc: gamma correction and greatly improved resampling
907 if (gl_lerpimages.value)
910 byte *inrow, *out, *row1, *row2;
911 float f, fstep, l1, l2;
913 fstep = (float) inheight/outheight;
915 row1 = malloc(outwidth*4);
916 row2 = malloc(outwidth*4);
919 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
920 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
921 for (i = 0, f = 0;i < outheight;i++,f += fstep)
926 inrow = (byte *)((int)indata + inwidth*4*yi);
928 memcpy(row1, row2, outwidth*4);
930 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
931 if (yi < (inheight-1))
932 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
934 memcpy(row2, row1, outwidth*4);
937 if (yi < (inheight-1))
941 for (j = 0;j < outwidth;j++)
943 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
944 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
945 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
946 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
951 else // last line has no pixels to lerp to
953 for (j = 0;j < outwidth;j++)
969 unsigned frac, fracstep;
970 byte *inrow, *out, *inpix;
973 fracstep = inwidth*0x10000/outwidth;
974 for (i=0 ; i<outheight ; i++)
976 inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
977 frac = fracstep >> 1;
978 for (j=0 ; j<outwidth ; j+=4)
980 inpix = inrow + ((frac >> 14) & ~3);*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
981 inpix = inrow + ((frac >> 14) & ~3);*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
982 inpix = inrow + ((frac >> 14) & ~3);*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
983 inpix = inrow + ((frac >> 14) & ~3);*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = gamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
991 GL_Resample8BitTexture -- JACK
994 void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
997 unsigned char *inrow;
998 unsigned frac, fracstep;
1000 fracstep = inwidth*0x10000/outwidth;
1001 for (i=0 ; i<outheight ; i++, out += outwidth)
1003 inrow = in + inwidth*(i*inheight/outheight);
1004 frac = fracstep >> 1;
1005 for (j=0 ; j<outwidth ; j+=4)
1007 out[j] = inrow[frac>>16];
1009 out[j+1] = inrow[frac>>16];
1011 out[j+2] = inrow[frac>>16];
1013 out[j+3] = inrow[frac>>16];
1024 Operates in place, quartering the size of the texture
1027 void GL_MipMap (byte *in, int width, int height)
1035 for (i=0 ; i<height ; i++, in+=width)
1037 for (j=0 ; j<width ; j+=8, out+=4, in+=8)
1039 out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
1040 out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
1041 out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
1042 out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
1051 Mipping for 8 bit textures
1054 void GL_MipMap8Bit (byte *in, int width, int height)
1057 unsigned short r,g,b;
1058 byte *out, *at1, *at2, *at3, *at4;
1062 for (i=0 ; i<height ; i++, in+=width)
1064 for (j=0 ; j<width ; j+=2, out+=1, in+=2)
1066 at1 = (byte *) (d_8to24table + in[0]);
1067 at2 = (byte *) (d_8to24table + in[1]);
1068 at3 = (byte *) (d_8to24table + in[width+0]);
1069 at4 = (byte *) (d_8to24table + in[width+1]);
1071 r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
1072 g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
1073 b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
1075 out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
1085 void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha)
1087 int samples, scaled_width, scaled_height, i;
1088 byte *in, *out, *scaled;
1090 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1092 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1095 scaled_width >>= (int)gl_picmip.value;
1096 scaled_height >>= (int)gl_picmip.value;
1098 if (scaled_width > gl_max_size.value)
1099 scaled_width = gl_max_size.value;
1100 if (scaled_height > gl_max_size.value)
1101 scaled_height = gl_max_size.value;
1107 for (i = 3;i < width*height*4;i += 4)
1115 samples = alpha ? gl_alpha_format : gl_solid_format;
1119 gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1120 else if (scaled_width == width && scaled_height == height)
1121 glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1124 gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, scaled, scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
1125 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1128 texels += scaled_width * scaled_height;
1130 scaled = malloc(scaled_width*scaled_height*4);
1131 if (scaled_width == width && scaled_height == height)
1133 // LordHavoc: gamma correct while copying
1135 out = (byte *)scaled;
1136 for (i = 0;i < width*height;i++)
1138 *out++ = gamma[*in++];
1139 *out++ = gamma[*in++];
1140 *out++ = gamma[*in++];
1145 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
1147 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1153 while (scaled_width > 1 || scaled_height > 1)
1155 GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
1157 scaled_height >>= 1;
1158 if (scaled_width < 1)
1160 if (scaled_height < 1)
1163 glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1171 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1172 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1176 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1177 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1182 void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap)
1184 int scaled_width, scaled_height;
1187 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1189 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1192 scaled_width >>= (int)gl_picmip.value;
1193 scaled_height >>= (int)gl_picmip.value;
1195 if (scaled_width > gl_max_size.value)
1196 scaled_width = gl_max_size.value;
1197 if (scaled_height > gl_max_size.value)
1198 scaled_height = gl_max_size.value;
1200 texels += scaled_width * scaled_height;
1202 if (scaled_width == width && scaled_height == height)
1206 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
1209 scaled = malloc(scaled_width*scaled_height*4);
1210 memcpy (scaled, data, width*height);
1214 scaled = malloc(scaled_width*scaled_height*4);
1215 GL_Resample8BitTexture (data, width, height, (void*) &scaled, scaled_width, scaled_height);
1218 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1224 while (scaled_width > 1 || scaled_height > 1)
1226 GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
1228 scaled_height >>= 1;
1229 if (scaled_width < 1)
1231 if (scaled_height < 1)
1234 glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1242 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1243 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1247 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1248 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1253 qboolean VID_Is8bit();
1260 void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
1262 static unsigned *trans;
1270 trans = malloc(s*4);
1271 // if there are no transparent pixels, make it a 3 component
1272 // texture even if it was specified as otherwise
1276 for (i=0 ; i<s ; i++)
1280 trans[i] = d_8to24table[p];
1283 trans[i] = 0; // force to black
1290 if (VID_Is8bit() && (data!=scrap_texels[0]))
1292 GL_Upload8_EXT (data, width, height, mipmap);
1301 // LordHavoc: dodge the copy if it will be uploaded as 8bit
1302 if (VID_Is8bit() && (data!=scrap_texels[0]))
1304 GL_Upload8_EXT (data, width, height, mipmap);
1309 // Sys_Error ("GL_Upload8: s&3");
1313 *outdata++ = d_8to24table[*indata++];
1316 *outdata++ = d_8to24table[*indata++];
1317 *outdata++ = d_8to24table[*indata++];
1319 for (i = 0;i < s;i+=4)
1321 *outdata++ = d_8to24table[*indata++];
1322 *outdata++ = d_8to24table[*indata++];
1323 *outdata++ = d_8to24table[*indata++];
1324 *outdata++ = d_8to24table[*indata++];
1328 GL_Upload32 (trans, width, height, mipmap, alpha);
1337 int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
1346 // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
1347 crc = CRC_Block(data, width*height*bytesperpixel);
1348 // see if the texture is already present
1351 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
1353 if (!strcmp (identifier, glt->identifier))
1355 // LordHavoc: everyone hates cache mismatchs, so I fixed it
1356 if (crc != glt->crc || width != glt->width || height != glt->height)
1358 Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
1359 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
1360 //Sys_Error ("GL_LoadTexture: cache mismatch");
1362 if ((gl_lerpimages.value != 0) != glt->lerped)
1363 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
1368 // LordHavoc: although this could be an else condition as it was in the original id code,
1369 // it is more clear this way
1370 // LordHavoc: check if there are still slots available
1371 if (numgltextures >= MAX_GLTEXTURES)
1372 Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
1373 glt = &gltextures[numgltextures++];
1375 strcpy (glt->identifier, identifier);
1376 glt->texnum = texture_extension_number;
1377 texture_extension_number++;
1378 // LordHavoc: label to drop out of the loop into the setup code
1379 GL_LoadTexture_setup:
1380 glt->crc = crc; // LordHavoc: used to verify textures are identical
1382 glt->height = height;
1383 glt->mipmap = mipmap;
1384 glt->bytesperpixel = bytesperpixel;
1385 glt->lerped = gl_lerpimages.value != 0;
1387 glBindTexture(GL_TEXTURE_2D, glt->texnum);
1389 if (bytesperpixel == 1) // 8bit
1390 GL_Upload8 (data, width, height, mipmap, alpha);
1392 GL_Upload32 (data, width, height, mipmap, true);
1393 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1403 int GL_LoadPicTexture (qpic_t *pic)
1405 return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
1408 int GL_GetTextureSlots (int count)
1410 gltexture_t *glt, *first;
1412 first = glt = &gltextures[numgltextures];
1415 glt->identifier[0] = 0;
1416 glt->texnum = texture_extension_number++;
1420 glt->bytesperpixel = 0;
1424 return first->texnum;