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 void Draw_Init (void)
378 Cvar_RegisterVariable (&qsg_version);
379 Cvar_RegisterVariable (&gl_max_size);
380 Cvar_RegisterVariable (&gl_picmip);
381 Cvar_RegisterVariable (&gl_conalpha);
382 Cvar_RegisterVariable (&gl_lerpimages);
384 // 3dfx can only handle 256 wide textures
385 if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
386 strstr((char *)gl_renderer, "Glide"))
387 Cvar_Set ("gl_max_size", "256");
389 Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
391 Cmd_AddCommand ("loadsky", &LoadSky_f);
393 // load the console background and the charset
394 // by hand, because we need to write the version
395 // string into the background before turning
397 draw_chars = W_GetLumpName ("conchars");
398 for (i=0 ; i<256*64 ; i++)
399 if (draw_chars[i] == 0)
400 draw_chars[i] = 255; // proper transparent color
402 // now turn them into textures
403 char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
405 start = Hunk_LowMark();
407 cb = (qpic_t *)COM_LoadMallocFile ("gfx/conback.lmp", false);
409 Sys_Error ("Couldn't load gfx/conback.lmp");
412 // hack the version number directly into the pic
414 #if defined(__linux__)
415 sprintf (ver, "DPNehahra Linux GL %.2f", (float) VERSION);
417 sprintf (ver, "DPNehahra Windows GL %.2f", (float) VERSION);
420 #if defined(__linux__)
421 sprintf (ver, "DarkPlaces Linux GL %.2f", (float)VERSION);
423 sprintf (ver, "DarkPlaces Windows GL %.2f", (float)VERSION);
426 dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
428 for (x=0 ; x<y ; x++)
429 Draw_CharToConback (ver[x], dest+(x<<3));
431 gl = (glpic_t *)conback->data;
432 gl->texnum = GL_LoadTexture ("conback", cb->width, cb->height, cb->data, false, false, 1);
437 conback->width = vid.width;
438 conback->height = vid.height;
440 // free loaded console
443 // save a texture slot for translated picture
444 translate_texture = texture_extension_number++;
446 // save slots for scraps
447 scrap_texnum = texture_extension_number;
448 texture_extension_number += MAX_SCRAPS;
451 // get the other pics we need
453 draw_disc = Draw_PicFromWad ("disc");
455 rmain_registercvars();
463 Draws one 8*8 graphics character with 0 being transparent.
464 It can be clipped to the top of the screen to allow the console to be
465 smoothly scrolled off.
468 void Draw_Character (int x, int y, int num)
471 float frow, fcol, size;
479 return; // totally off screen
488 glBindTexture(GL_TEXTURE_2D, char_texture);
489 // LordHavoc: NEAREST mode on text if not scaling up
490 if ((int) vid.width < glwidth)
492 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
493 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
498 glTexCoord2f (fcol, frow);
500 glTexCoord2f (fcol + size, frow);
502 glTexCoord2f (fcol + size, frow + size);
503 glVertex2f (x+8, y+8);
504 glTexCoord2f (fcol, frow + size);
508 // LordHavoc: revert to LINEAR mode
509 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
510 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
518 // LordHavoc: sped this up a lot, and added maxlen
519 void Draw_String (int x, int y, char *str, int maxlen)
523 if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print
526 maxlen = strlen(str);
527 else if (maxlen > (int) strlen(str))
528 maxlen = strlen(str);
529 glBindTexture(GL_TEXTURE_2D, char_texture);
531 // LordHavoc: NEAREST mode on text if not scaling up
532 if ((int) vid.width < glwidth)
534 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
535 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
540 while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room
542 if ((num = *str++) != 32) // skip spaces
544 frow = (float) ((int) num >> 4)*0.0625;
545 fcol = (float) ((int) num & 15)*0.0625;
546 glTexCoord2f (fcol, frow);
548 glTexCoord2f (fcol + 0.0625, frow);
550 glTexCoord2f (fcol + 0.0625, frow + 0.0625);
551 glVertex2f (x+8, y+8);
552 glTexCoord2f (fcol, frow + 0.0625);
559 // LordHavoc: revert to LINEAR mode
560 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
561 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
569 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
575 gl = (glpic_t *)pic->data;
576 // glDisable(GL_ALPHA_TEST);
577 // glEnable (GL_BLEND);
578 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
579 // glCullFace(GL_FRONT);
580 glColor4f(0.8,0.8,0.8,alpha);
581 glBindTexture(GL_TEXTURE_2D, gl->texnum);
582 // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
584 glTexCoord2f (gl->sl, gl->tl);
586 glTexCoord2f (gl->sh, gl->tl);
587 glVertex2f (x+pic->width, y);
588 glTexCoord2f (gl->sh, gl->th);
589 glVertex2f (x+pic->width, y+pic->height);
590 glTexCoord2f (gl->sl, gl->th);
591 glVertex2f (x, y+pic->height);
594 // glEnable(GL_ALPHA_TEST);
595 // glDisable (GL_BLEND);
604 void Draw_Pic (int x, int y, qpic_t *pic)
610 gl = (glpic_t *)pic->data;
611 glColor3f(0.8,0.8,0.8);
612 glBindTexture(GL_TEXTURE_2D, gl->texnum);
614 glTexCoord2f (gl->sl, gl->tl);
616 glTexCoord2f (gl->sh, gl->tl);
617 glVertex2f (x+pic->width, y);
618 glTexCoord2f (gl->sh, gl->th);
619 glVertex2f (x+pic->width, y+pic->height);
620 glTexCoord2f (gl->sl, gl->th);
621 glVertex2f (x, y+pic->height);
631 void Draw_TransPic (int x, int y, qpic_t *pic)
633 if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || (unsigned)(y + pic->height) > vid.height)
634 Sys_Error ("Draw_TransPic: bad coordinates");
636 // glEnable(GL_BLEND);
637 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
638 // glDisable(GL_ALPHA_TEST);
639 Draw_Pic (x, y, pic);
640 // glDisable(GL_BLEND);
646 Draw_TransPicTranslate
648 Only used for the player color selection menu
651 void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
654 unsigned trans[64*64], *dest;
658 glBindTexture(GL_TEXTURE_2D, translate_texture);
660 c = pic->width * pic->height;
663 for (v=0 ; v<64 ; v++, dest += 64)
665 src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
666 for (u=0 ; u<64 ; u++)
668 p = src[(u*pic->width)>>6];
672 dest[u] = d_8to24table[translation[p]];
676 glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
678 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
679 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
681 glColor3f(0.8,0.8,0.8);
686 glVertex2f (x+pic->width, y);
688 glVertex2f (x+pic->width, y+pic->height);
690 glVertex2f (x, y+pic->height);
697 Draw_ConsoleBackground
701 void Draw_ConsoleBackground (int lines)
703 // LordHavoc: changed alpha
704 //int y = (vid.height >> 1);
706 if (lines >= (int) vid.height)
707 Draw_Pic(0, lines - vid.height, conback);
709 Draw_AlphaPic (0, lines - vid.height, conback, gl_conalpha.value*lines/vid.height);
710 // Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
717 Fills a box of pixels with a single color
720 void Draw_Fill (int x, int y, int w, int h, int c)
722 glDisable (GL_TEXTURE_2D);
723 glColor3f (host_basepal[c*3]/255.0, host_basepal[c*3+1]/255.0, host_basepal[c*3+2]/255.0);
729 glVertex2f (x+w, y+h);
734 glEnable (GL_TEXTURE_2D);
736 //=============================================================================
738 //=============================================================================
744 Setup as if the screen was 320*200
749 glViewport (glx, gly, glwidth, glheight);
751 glMatrixMode(GL_PROJECTION);
753 glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
755 glMatrixMode(GL_MODELVIEW);
758 glDisable (GL_DEPTH_TEST);
759 glDisable (GL_CULL_FACE);
760 glEnable (GL_BLEND); // was Disable
761 // glEnable (GL_ALPHA_TEST);
762 glDisable (GL_ALPHA_TEST);
763 glEnable(GL_TEXTURE_2D);
765 // LordHavoc: added this
766 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
767 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
772 // LordHavoc: SHOWLMP stuff
773 #define SHOWLMP_MAXLABELS 256
774 typedef struct showlmp_s
783 showlmp_t showlmp[SHOWLMP_MAXLABELS];
785 void SHOWLMP_decodehide()
789 lmplabel = MSG_ReadString();
790 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
791 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
793 showlmp[i].isactive = false;
798 void SHOWLMP_decodeshow()
801 byte lmplabel[256], picname[256];
803 strcpy(lmplabel,MSG_ReadString());
804 strcpy(picname, MSG_ReadString());
808 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
809 if (showlmp[i].isactive)
811 if (strcmp(showlmp[i].label, lmplabel) == 0)
814 break; // drop out to replace it
817 else if (k < 0) // find first empty one to replace
820 return; // none found to replace
821 // change existing one
822 showlmp[k].isactive = true;
823 strcpy(showlmp[k].label, lmplabel);
824 strcpy(showlmp[k].pic, picname);
829 void SHOWLMP_drawall()
832 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
833 if (showlmp[i].isactive)
834 Draw_TransPic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic));
840 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
841 showlmp[i].isactive = false;
844 //====================================================================
851 int GL_FindTexture (char *identifier)
856 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
858 if (!strcmp (identifier, glt->identifier))
859 return gltextures[i].texnum;
865 extern byte qgamma[];
867 // LordHavoc: gamma correction and improved resampling
868 void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
871 float f, fstep, l1, l2;
872 fstep = (float) inwidth/outwidth;
873 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
878 in += (xi - oldx) * 4;
881 if (xi < (inwidth-1))
885 *out++ = qgamma[(byte) (in[0] * l1 + in[4] * l2)];
886 *out++ = qgamma[(byte) (in[1] * l1 + in[5] * l2)];
887 *out++ = qgamma[(byte) (in[2] * l1 + in[6] * l2)];
888 *out++ = (byte) (in[3] * l1 + in[7] * l2) ;
890 else // last pixel of the line has no pixel to lerp to
892 *out++ = qgamma[in[0]];
893 *out++ = qgamma[in[1]];
894 *out++ = qgamma[in[2]];
905 void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
907 // LordHavoc: gamma correction and greatly improved resampling
908 if (gl_lerpimages.value)
911 byte *inrow, *out, *row1, *row2;
912 float f, fstep, l1, l2;
914 fstep = (float) inheight/outheight;
916 row1 = malloc(outwidth*4);
917 row2 = malloc(outwidth*4);
920 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
921 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
922 for (i = 0, f = 0;i < outheight;i++,f += fstep)
927 inrow = (byte *)((int)indata + inwidth*4*yi);
929 memcpy(row1, row2, outwidth*4);
931 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
932 if (yi < (inheight-1))
933 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
935 memcpy(row2, row1, outwidth*4);
938 if (yi < (inheight-1))
942 for (j = 0;j < outwidth;j++)
944 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
945 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
946 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
947 *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
952 else // last line has no pixels to lerp to
954 for (j = 0;j < outwidth;j++)
970 unsigned frac, fracstep;
971 byte *inrow, *out, *inpix;
974 fracstep = inwidth*0x10000/outwidth;
975 for (i=0 ; i<outheight ; i++)
977 inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
978 frac = fracstep >> 1;
979 for (j=0 ; j<outwidth ; j+=4)
981 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
982 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
983 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
984 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
992 GL_Resample8BitTexture -- JACK
995 void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
998 unsigned char *inrow;
999 unsigned frac, fracstep;
1001 fracstep = inwidth*0x10000/outwidth;
1002 for (i=0 ; i<outheight ; i++, out += outwidth)
1004 inrow = in + inwidth*(i*inheight/outheight);
1005 frac = fracstep >> 1;
1006 for (j=0 ; j<outwidth ; j+=4)
1008 out[j] = inrow[frac>>16];
1010 out[j+1] = inrow[frac>>16];
1012 out[j+2] = inrow[frac>>16];
1014 out[j+3] = inrow[frac>>16];
1025 Operates in place, quartering the size of the texture
1028 void GL_MipMap (byte *in, int width, int height)
1036 for (i=0 ; i<height ; i++, in+=width)
1038 for (j=0 ; j<width ; j+=8, out+=4, in+=8)
1040 out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
1041 out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
1042 out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
1043 out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
1052 Mipping for 8 bit textures
1055 void GL_MipMap8Bit (byte *in, int width, int height)
1058 unsigned short r,g,b;
1059 byte *out, *at1, *at2, *at3, *at4;
1063 for (i=0 ; i<height ; i++, in+=width)
1065 for (j=0 ; j<width ; j+=2, out+=1, in+=2)
1067 at1 = (byte *) (d_8to24table + in[0]);
1068 at2 = (byte *) (d_8to24table + in[1]);
1069 at3 = (byte *) (d_8to24table + in[width+0]);
1070 at4 = (byte *) (d_8to24table + in[width+1]);
1072 r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
1073 g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
1074 b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
1076 out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
1086 void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha)
1088 int samples, scaled_width, scaled_height, i;
1089 byte *in, *out, *scaled;
1091 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1093 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1096 scaled_width >>= (int)gl_picmip.value;
1097 scaled_height >>= (int)gl_picmip.value;
1099 if (scaled_width > gl_max_size.value)
1100 scaled_width = gl_max_size.value;
1101 if (scaled_height > gl_max_size.value)
1102 scaled_height = gl_max_size.value;
1108 for (i = 3;i < width*height*4;i += 4)
1116 samples = alpha ? gl_alpha_format : gl_solid_format;
1120 gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1121 else if (scaled_width == width && scaled_height == height)
1122 glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1125 gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, scaled, scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
1126 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1129 texels += scaled_width * scaled_height;
1131 scaled = malloc(scaled_width*scaled_height*4);
1132 if (scaled_width == width && scaled_height == height)
1134 // LordHavoc: gamma correct while copying
1136 out = (byte *)scaled;
1137 for (i = 0;i < width*height;i++)
1139 *out++ = qgamma[*in++];
1140 *out++ = qgamma[*in++];
1141 *out++ = qgamma[*in++];
1146 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
1148 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1154 while (scaled_width > 1 || scaled_height > 1)
1156 GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
1158 scaled_height >>= 1;
1159 if (scaled_width < 1)
1161 if (scaled_height < 1)
1164 glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1172 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1173 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1177 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1178 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1183 void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap)
1185 int scaled_width, scaled_height;
1186 byte *scaled = NULL;
1188 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1190 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1193 scaled_width >>= (int)gl_picmip.value;
1194 scaled_height >>= (int)gl_picmip.value;
1196 if (scaled_width > gl_max_size.value)
1197 scaled_width = gl_max_size.value;
1198 if (scaled_height > gl_max_size.value)
1199 scaled_height = gl_max_size.value;
1201 texels += scaled_width * scaled_height;
1203 if (scaled_width == width && scaled_height == height)
1207 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
1210 scaled = malloc(scaled_width*scaled_height*4);
1211 memcpy (scaled, data, width*height);
1215 scaled = malloc(scaled_width*scaled_height*4);
1216 GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
1219 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1225 while (scaled_width > 1 || scaled_height > 1)
1227 GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
1229 scaled_height >>= 1;
1230 if (scaled_width < 1)
1232 if (scaled_height < 1)
1235 glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1243 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1244 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1248 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1249 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1254 qboolean VID_Is8bit();
1261 void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
1263 static unsigned *trans;
1271 trans = malloc(s*4);
1272 // if there are no transparent pixels, make it a 3 component
1273 // texture even if it was specified as otherwise
1277 for (i=0 ; i<s ; i++)
1281 trans[i] = d_8to24table[p];
1284 trans[i] = 0; // force to black
1291 if (VID_Is8bit() && (data!=scrap_texels[0]))
1293 GL_Upload8_EXT (data, width, height, mipmap);
1302 // LordHavoc: dodge the copy if it will be uploaded as 8bit
1303 if (VID_Is8bit() && (data!=scrap_texels[0]))
1305 GL_Upload8_EXT (data, width, height, mipmap);
1310 // Sys_Error ("GL_Upload8: s&3");
1314 *outdata++ = d_8to24table[*indata++];
1317 *outdata++ = d_8to24table[*indata++];
1318 *outdata++ = d_8to24table[*indata++];
1320 for (i = 0;i < s;i+=4)
1322 *outdata++ = d_8to24table[*indata++];
1323 *outdata++ = d_8to24table[*indata++];
1324 *outdata++ = d_8to24table[*indata++];
1325 *outdata++ = d_8to24table[*indata++];
1329 GL_Upload32 (trans, width, height, mipmap, alpha);
1338 int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
1347 // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
1348 crc = CRC_Block(data, width*height*bytesperpixel);
1349 // see if the texture is already present
1352 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
1354 if (!strcmp (identifier, glt->identifier))
1356 // LordHavoc: everyone hates cache mismatchs, so I fixed it
1357 if (crc != glt->crc || width != glt->width || height != glt->height)
1359 Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
1360 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
1361 //Sys_Error ("GL_LoadTexture: cache mismatch");
1363 if ((gl_lerpimages.value != 0) != glt->lerped)
1364 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
1369 // LordHavoc: although this could be an else condition as it was in the original id code,
1370 // it is more clear this way
1371 // LordHavoc: check if there are still slots available
1372 if (numgltextures >= MAX_GLTEXTURES)
1373 Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
1374 glt = &gltextures[numgltextures++];
1376 strcpy (glt->identifier, identifier);
1377 glt->texnum = texture_extension_number;
1378 texture_extension_number++;
1379 // LordHavoc: label to drop out of the loop into the setup code
1380 GL_LoadTexture_setup:
1381 glt->crc = crc; // LordHavoc: used to verify textures are identical
1383 glt->height = height;
1384 glt->mipmap = mipmap;
1385 glt->bytesperpixel = bytesperpixel;
1386 glt->lerped = gl_lerpimages.value != 0;
1388 glBindTexture(GL_TEXTURE_2D, glt->texnum);
1390 if (bytesperpixel == 1) // 8bit
1391 GL_Upload8 (data, width, height, mipmap, alpha);
1393 GL_Upload32 (data, width, height, mipmap, true);
1394 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1404 int GL_LoadPicTexture (qpic_t *pic)
1406 return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
1409 int GL_GetTextureSlots (int count)
1411 gltexture_t *glt, *first;
1413 first = glt = &gltextures[numgltextures];
1416 glt->identifier[0] = 0;
1417 glt->texnum = texture_extension_number++;
1421 glt->bytesperpixel = 0;
1425 return first->texnum;