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