|
|
1.1 root 1:
2: // draw.c -- this is the only file outside the refresh that touches the
3: // vid buffer
4:
5: #include "quakedef.h"
6:
7: cvar_t gl_nobind = {"gl_nobind", "0"};
8: cvar_t gl_max_size = {"gl_max_size", "1024"};
9: cvar_t gl_round_down = {"gl_round_down", "1"};
10: cvar_t gl_picmip = {"gl_picmip", "0"};
11:
12: byte *draw_chars; // 8*8 graphic characters
13: qpic_t *draw_disc;
14: qpic_t *draw_backtile;
15:
16: int translate_texture;
17: int char_texture;
18:
19: typedef struct
20: {
21: int texnum;
22: float sl, tl, sh, th;
23: } glpic_t;
24:
25: byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
26: qpic_t *conback = (qpic_t *)&conback_buffer;
27:
28: int gl_lightmap_format = 4;
29: int gl_solid_format = 3;
30: int gl_alpha_format = 4;
31:
32: int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
33: int gl_filter_max = GL_LINEAR;
34:
35:
36: int texels;
37:
38: typedef struct
39: {
40: int texnum;
41: char identifier[64];
42: int width, height;
43: qboolean mipmap;
44: } gltexture_t;
45:
46: #define MAX_GLTEXTURES 1024
47: gltexture_t gltextures[MAX_GLTEXTURES];
48: int numgltextures;
49:
50:
51: void GL_Bind (int texnum)
52: {
53: if (gl_nobind.value)
54: texnum = char_texture;
55: if (currenttexture == texnum)
56: return;
57: currenttexture = texnum;
58: bindTexFunc (GL_TEXTURE_2D, texnum);
59: }
60:
61: void GL_Texels_f (void)
62: {
63: Con_Printf ("Current uploaded texels: %i\n", texels);
64: }
65:
66: /*
67: =============================================================================
68:
69: scrap allocation
70:
71: Allocate all the little status bar obejcts into a single texture
72: to crutch up stupid hardware / drivers
73:
74: =============================================================================
75: */
76:
77: #define MAX_SCRAPS 1
78: #define BLOCK_WIDTH 256
79: #define BLOCK_HEIGHT 256
80:
81: int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
82: byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
83: qboolean scrap_dirty;
84: int scrap_texnum;
85:
86: // returns a texture number and the position inside it
87: int Scrap_AllocBlock (int w, int h, int *x, int *y)
88: {
89: int i, j;
90: int best, best2;
91: int bestx;
92: int texnum;
93:
94: for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
95: {
96: best = BLOCK_HEIGHT;
97:
98: for (i=0 ; i<BLOCK_WIDTH-w ; i++)
99: {
100: best2 = 0;
101:
102: for (j=0 ; j<w ; j++)
103: {
104: if (scrap_allocated[texnum][i+j] >= best)
105: break;
106: if (scrap_allocated[texnum][i+j] > best2)
107: best2 = scrap_allocated[texnum][i+j];
108: }
109: if (j == w)
110: { // this is a valid spot
111: *x = i;
112: *y = best = best2;
113: }
114: }
115:
116: if (best + h > BLOCK_HEIGHT)
117: continue;
118:
119: for (i=0 ; i<w ; i++)
120: scrap_allocated[texnum][*x + i] = best + h;
121:
122: return texnum;
123: }
124:
125: return -1;
126: // Sys_Error ("Scrap_AllocBlock: full");
127: }
128:
129: int scrap_uploads;
130:
131: void Scrap_Upload (void)
132: {
133: scrap_uploads++;
134: GL_Bind(scrap_texnum);
135: GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
136: scrap_dirty = false;
137: }
138:
139: //=============================================================================
140: /* Support Routines */
141:
142: typedef struct cachepic_s
143: {
144: char name[MAX_QPATH];
145: qpic_t pic;
146: byte padding[32]; // for appended glpic
147: } cachepic_t;
148:
149: #define MAX_CACHED_PICS 128
150: cachepic_t menu_cachepics[MAX_CACHED_PICS];
151: int menu_numcachepics;
152:
153: byte menuplyr_pixels[4096];
154:
155: int pic_texels;
156: int pic_count;
157:
158: qpic_t *Draw_PicFromWad (char *name)
159: {
160: qpic_t *p;
161: glpic_t *gl;
162:
163: p = W_GetLumpName (name);
164: gl = (glpic_t *)p->data;
165:
166: // load little ones into the scrap
167: if (p->width < 64 && p->height < 64)
168: {
169: int x, y;
170: int i, j, k;
171: int texnum;
172:
173: texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
174: if (texnum == -1)
175: goto nonscrap;
176: scrap_dirty = true;
177: k = 0;
178: for (i=0 ; i<p->height ; i++)
179: for (j=0 ; j<p->width ; j++, k++)
180: scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
181: texnum += scrap_texnum;
182: gl->texnum = texnum;
183: gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
184: gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
185: gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
186: gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
187:
188: pic_count++;
189: pic_texels += p->width*p->height;
190: }
191: else
192: {
193: nonscrap:
194: gl->texnum = GL_LoadPicTexture (p);
195: gl->sl = 0;
196: gl->sh = 1;
197: gl->tl = 0;
198: gl->th = 1;
199: }
200: return p;
201: }
202:
203:
204: /*
205: ================
206: Draw_CachePic
207: ================
208: */
209: qpic_t *Draw_CachePic (char *path)
210: {
211: cachepic_t *pic;
212: int i;
213: qpic_t *dat;
214: glpic_t *gl;
215:
216: for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
217: if (!strcmp (path, pic->name))
218: return &pic->pic;
219:
220: if (menu_numcachepics == MAX_CACHED_PICS)
221: Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
222: menu_numcachepics++;
223: strcpy (pic->name, path);
224:
225: //
226: // load the pic from disk
227: //
228: dat = (qpic_t *)COM_LoadTempFile (path);
229: if (!dat)
230: Sys_Error ("Draw_CachePic: failed to load %s", path);
231: SwapPic (dat);
232:
233: // HACK HACK HACK --- we need to keep the bytes for
234: // the translatable player picture just for the menu
235: // configuration dialog
236: if (!strcmp (path, "gfx/menuplyr.lmp"))
237: memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
238:
239: pic->pic.width = dat->width;
240: pic->pic.height = dat->height;
241:
242: gl = (glpic_t *)pic->pic.data;
243: gl->texnum = GL_LoadPicTexture (dat);
244: gl->sl = 0;
245: gl->sh = 1;
246: gl->tl = 0;
247: gl->th = 1;
248:
249: return &pic->pic;
250: }
251:
252:
253: void Draw_CharToConback (int num, byte *dest)
254: {
255: int row, col;
256: byte *source;
257: int drawline;
258: int x;
259:
260: row = num>>4;
261: col = num&15;
262: source = draw_chars + (row<<10) + (col<<3);
263:
264: drawline = 8;
265:
266: while (drawline--)
267: {
268: for (x=0 ; x<8 ; x++)
269: if (source[x] != 255)
270: dest[x] = 0x60 + source[x];
271: source += 128;
272: dest += 320;
273: }
274:
275: }
276:
277: typedef struct
278: {
279: char *name;
280: int minimize, maximize;
281: } mode_t;
282:
283: mode_t modes[] = {
284: {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
285: {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
286: {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
287: {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
288: {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
289: {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
290: };
291:
292: /*
293: ===============
294: Draw_TextureMode_f
295: ===============
296: */
297: void Draw_TextureMode_f (void)
298: {
299: int i;
300: gltexture_t *glt;
301:
302: if (Cmd_Argc() == 1)
303: {
304: for (i=0 ; i< 6 ; i++)
305: if (gl_filter_min == modes[i].minimize)
306: {
307: Con_Printf ("%s\n", modes[i].name);
308: return;
309: }
310: Con_Printf ("current filter is unknown???\n");
311: return;
312: }
313:
314: for (i=0 ; i< 6 ; i++)
315: {
316: if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
317: break;
318: }
319: if (i == 6)
320: {
321: Con_Printf ("bad filter name\n");
322: return;
323: }
324:
325: gl_filter_min = modes[i].minimize;
326: gl_filter_max = modes[i].maximize;
327:
328: // change all the existing mipmap texture objects
329: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
330: {
331: if (glt->mipmap)
332: {
333: GL_Bind (glt->texnum);
334: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
335: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
336: }
337: }
338: }
339:
340: /*
341: ===============
342: Draw_Init
343: ===============
344: */
345: void Draw_Init (void)
346: {
347: int i;
348: qpic_t *cb;
349: byte *dest;
350: int x, y;
351: char ver[40];
352: glpic_t *gl;
353:
354: Cvar_RegisterVariable (&gl_nobind);
355: Cvar_RegisterVariable (&gl_max_size);
356: Cvar_RegisterVariable (&gl_round_down);
357: Cvar_RegisterVariable (&gl_picmip);
358:
359: // 3dfx can only handle 256 wide textures
360: if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4))
361: Cvar_Set ("gl_max_size", "256");
362:
363: Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
364: Cmd_AddCommand ("gl_texels", &GL_Texels_f);
365:
366:
367: // load the console background and the charset
368: // by hand, because we need to write the version
369: // string into the background before turning
370: // it into a texture
371: draw_chars = W_GetLumpName ("conchars");
372: for (i=0 ; i<256*64 ; i++)
373: if (draw_chars[i] == 0)
374: draw_chars[i] = 255; // proper transparent color
375:
376: cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp");
377: if (!cb)
378: Sys_Error ("Couldn't load gfx/conback.lmp");
379: SwapPic (cb);
380:
381: // hack the version number directly into the pic
382: sprintf (ver, "(gl %4.2f) %4.2f", (float)GLQUAKE_VERSION, (float)VERSION);
383: dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
384: y = strlen(ver);
385: for (x=0 ; x<y ; x++)
386: Draw_CharToConback (ver[x], dest+(x<<3));
387:
388: // now turn them into textures
389: char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
390: conback->width = cb->width;
391: conback->height = cb->height;
392: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
393: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
394:
395: gl = (glpic_t *)conback->data;
396: gl->texnum = GL_LoadTexture ("conback", 320, 200, cb->data, false, false);
397: gl->sl = 0;
398: gl->sh = 1;
399: gl->tl = 0;
400: gl->th = 1;
401:
402: // save a texture slot for translated picture
403: translate_texture = texture_extension_number++;
404:
405: // save slots for scraps
406: scrap_texnum = texture_extension_number;
407: texture_extension_number += MAX_SCRAPS;
408:
409: //
410: // get the other pics we need
411: //
412: draw_disc = Draw_PicFromWad ("disc");
413: draw_backtile = Draw_PicFromWad ("backtile");
414: }
415:
416:
417:
418: /*
419: ================
420: Draw_Character
421:
422: Draws one 8*8 graphics character with 0 being transparent.
423: It can be clipped to the top of the screen to allow the console to be
424: smoothly scrolled off.
425: ================
426: */
427: void Draw_Character (int x, int y, int num)
428: {
429: byte *dest;
430: byte *source;
431: unsigned short *pusdest;
432: int drawline;
433: int row, col;
434: float frow, fcol, size;
435:
436: if (num == 32)
437: return; // space
438:
439: num &= 255;
440:
441: if (y <= -8)
442: return; // totally off screen
443:
444: row = num>>4;
445: col = num&15;
446:
447: frow = row*0.0625;
448: fcol = col*0.0625;
449: size = 0.0625;
450:
451: GL_Bind (char_texture);
452:
453: glBegin (GL_QUADS);
454: glTexCoord2f (fcol, frow);
455: glVertex2f (x, y);
456: glTexCoord2f (fcol + size, frow);
457: glVertex2f (x+8, y);
458: glTexCoord2f (fcol + size, frow + size);
459: glVertex2f (x+8, y+8);
460: glTexCoord2f (fcol, frow + size);
461: glVertex2f (x, y+8);
462: glEnd ();
463: }
464:
465: /*
466: ================
467: Draw_String
468: ================
469: */
470: void Draw_String (int x, int y, char *str)
471: {
472: while (*str)
473: {
474: Draw_Character (x, y, *str);
475: str++;
476: x += 8;
477: }
478: }
479:
480: /*
481: ================
482: Draw_DebugChar
483:
484: Draws a single character directly to the upper right corner of the screen.
485: This is for debugging lockups by drawing different chars in different parts
486: of the code.
487: ================
488: */
489: void Draw_DebugChar (char num)
490: {
491: }
492:
493: /*
494: =============
495: Draw_Pic
496: =============
497: */
498: void Draw_Pic (int x, int y, qpic_t *pic)
499: {
500: byte *dest, *source;
501: unsigned short *pusdest;
502: int v, u;
503: glpic_t *gl;
504:
505: if (scrap_dirty)
506: Scrap_Upload ();
507: gl = (glpic_t *)pic->data;
508: glColor4f (1,1,1,1);
509: GL_Bind (gl->texnum);
510: glBegin (GL_QUADS);
511: glTexCoord2f (gl->sl, gl->tl);
512: glVertex2f (x, y);
513: glTexCoord2f (gl->sh, gl->tl);
514: glVertex2f (x+pic->width, y);
515: glTexCoord2f (gl->sh, gl->th);
516: glVertex2f (x+pic->width, y+pic->height);
517: glTexCoord2f (gl->sl, gl->th);
518: glVertex2f (x, y+pic->height);
519: glEnd ();
520: }
521:
522:
523: /*
524: =============
525: Draw_TransPic
526: =============
527: */
528: void Draw_TransPic (int x, int y, qpic_t *pic)
529: {
530: byte *dest, *source, tbyte;
531: unsigned short *pusdest;
532: int v, u;
533:
534: if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
535: (unsigned)(y + pic->height) > vid.height)
536: {
537: Sys_Error ("Draw_TransPic: bad coordinates");
538: }
539:
540: Draw_Pic (x, y, pic);
541: }
542:
543:
544: /*
545: =============
546: Draw_TransPicTranslate
547:
548: Only used for the player color selection menu
549: =============
550: */
551: void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
552: {
553: int v, u, c;
554: unsigned trans[64*64], *dest;
555: byte *src;
556: int p;
557:
558: GL_Bind (translate_texture);
559:
560: c = pic->width * pic->height;
561:
562: dest = trans;
563: for (v=0 ; v<64 ; v++, dest += 64)
564: {
565: src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
566: for (u=0 ; u<64 ; u++)
567: {
568: p = src[(u*pic->width)>>6];
569: if (p == 255)
570: dest[u] = p;
571: else
572: dest[u] = d_8to24table[translation[p]];
573: }
574: }
575:
576: glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
577:
578: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
579: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
580:
581: glColor3f (1,1,1);
582: glBegin (GL_QUADS);
583: glTexCoord2f (0, 0);
584: glVertex2f (x, y);
585: glTexCoord2f (1, 0);
586: glVertex2f (x+pic->width, y);
587: glTexCoord2f (1, 1);
588: glVertex2f (x+pic->width, y+pic->height);
589: glTexCoord2f (0, 1);
590: glVertex2f (x, y+pic->height);
591: glEnd ();
592: }
593:
594:
595: /*
596: ================
597: Draw_ConsoleBackground
598:
599: ================
600: */
601: void Draw_ConsoleBackground (int lines)
602: {
603: Draw_Pic (0, lines-200, conback);
604: }
605:
606:
607: /*
608: =============
609: Draw_TileClear
610:
611: This repeats a 64*64 tile graphic to fill the screen around a sized down
612: refresh window.
613: =============
614: */
615: void Draw_TileClear (int x, int y, int w, int h)
616: {
617: glColor3f (1,1,1);
618: GL_Bind (*(int *)draw_backtile->data);
619: glBegin (GL_QUADS);
620: glTexCoord2f (x/64.0, y/64.0);
621: glVertex2f (x, y);
622: glTexCoord2f ( (x+w)/64.0, y/64.0);
623: glVertex2f (x+w, y);
624: glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
625: glVertex2f (x+w, y+h);
626: glTexCoord2f ( x/64.0, (y+h)/64.0 );
627: glVertex2f (x, y+h);
628: glEnd ();
629: }
630:
631:
632: /*
633: =============
634: Draw_Fill
635:
636: Fills a box of pixels with a single color
637: =============
638: */
639: void Draw_Fill (int x, int y, int w, int h, int c)
640: {
641: glDisable (GL_TEXTURE_2D);
642: glColor3f (host_basepal[c*3]/255.0,
643: host_basepal[c*3+1]/255.0,
644: host_basepal[c*3+2]/255.0);
645:
646: glBegin (GL_QUADS);
647:
648: glVertex2f (x,y);
649: glVertex2f (x+w, y);
650: glVertex2f (x+w, y+h);
651: glVertex2f (x, y+h);
652:
653: glEnd ();
654: glColor3f (1,1,1);
655: glEnable (GL_TEXTURE_2D);
656: }
657: //=============================================================================
658:
659: /*
660: ================
661: Draw_FadeScreen
662:
663: ================
664: */
665: void Draw_FadeScreen (void)
666: {
667: glEnable (GL_BLEND);
668: glDisable (GL_TEXTURE_2D);
669: glColor4f (0, 0, 0, 0.8);
670: glBegin (GL_QUADS);
671:
672: glVertex2f (0,0);
673: glVertex2f (320, 0);
674: glVertex2f (320, 200);
675: glVertex2f (0, 200);
676:
677: glEnd ();
678: glColor4f (1,1,1,1);
679: glEnable (GL_TEXTURE_2D);
680: glDisable (GL_BLEND);
681:
682: Sbar_Changed();
683: }
684:
685: //=============================================================================
686:
687: /*
688: ================
689: Draw_BeginDisc
690:
691: Draws the little blue disc in the corner of the screen.
692: Call before beginning any disc IO.
693: ================
694: */
695: void Draw_BeginDisc (void)
696: {
697: if (!draw_disc)
698: return;
699: glDrawBuffer (GL_FRONT);
700: Draw_Pic (320 - 24, 0, draw_disc);
701: glDrawBuffer (GL_BACK);
702: }
703:
704:
705: /*
706: ================
707: Draw_EndDisc
708:
709: Erases the disc icon.
710: Call after completing any disc IO
711: ================
712: */
713: void Draw_EndDisc (void)
714: {
715: }
716:
717: /*
718: ================
719: GL_Set2D
720:
721: Setup as if the screen was 320*200
722: ================
723: */
724: void GL_Set2D (void)
725: {
726: glViewport (glx, gly, glwidth, glheight);
727:
728: glMatrixMode(GL_PROJECTION);
729: glLoadIdentity ();
730: glOrtho (0, 320, 200, 0, -99999, 99999);
731:
732: glMatrixMode(GL_MODELVIEW);
733: glLoadIdentity ();
734:
735: glDisable (GL_DEPTH_TEST);
736: glDisable (GL_CULL_FACE);
737: glDisable (GL_BLEND);
738: glEnable (GL_ALPHA_TEST);
739: // glDisable (GL_ALPHA_TEST);
740:
741: glColor4f (1,1,1,1);
742: }
743:
744: //====================================================================
745:
746: /*
747: ================
748: GL_FindTexture
749: ================
750: */
751: int GL_FindTexture (char *identifier)
752: {
753: int i;
754: gltexture_t *glt;
755:
756: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
757: {
758: if (!strcmp (identifier, glt->identifier))
759: return gltextures[i].texnum;
760: }
761:
762: return -1;
763: }
764:
765: /*
766: ================
767: GL_ResampleTexture
768: ================
769: */
770: void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
771: {
772: int i, j;
773: unsigned *inrow, *inrow2;
774: unsigned frac, fracstep;
775: unsigned p1[1024], p2[1024];
776: byte *pix1, *pix2, *pix3, *pix4;
777:
778: fracstep = inwidth*0x10000/outwidth;
779:
780: frac = fracstep>>2;
781: for (i=0 ; i<outwidth ; i++)
782: {
783: p1[i] = 4*(frac>>16);
784: frac += fracstep;
785: }
786: frac = 3*(fracstep>>2);
787: for (i=0 ; i<outwidth ; i++)
788: {
789: p2[i] = 4*(frac>>16);
790: frac += fracstep;
791: }
792:
793: for (i=0 ; i<outheight ; i++, out += outwidth)
794: {
795: inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
796: inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
797: frac = fracstep >> 1;
798: for (j=0 ; j<outwidth ; j++)
799: {
800: pix1 = (byte *)inrow + p1[j];
801: pix2 = (byte *)inrow + p2[j];
802: pix3 = (byte *)inrow2 + p1[j];
803: pix4 = (byte *)inrow2 + p2[j];
804: ((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
805: ((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
806: ((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
807: ((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
808: }
809: }
810: }
811:
812: /*
813: ================
814: GL_MipMap
815:
816: Operates in place, quartering the size of the texture
817: ================
818: */
819: void GL_MipMap (byte *in, int width, int height)
820: {
821: int i, j;
822: byte *out;
823:
824: width <<=2;
825: height >>= 1;
826: out = in;
827: for (i=0 ; i<height ; i++, in+=width)
828: {
829: for (j=0 ; j<width ; j+=8, out+=4, in+=8)
830: {
831: out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
832: out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
833: out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
834: out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
835: }
836: }
837: }
838:
839: /*
840: ===============
841: GL_Upload32
842: ===============
843: */
844: void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha)
845: {
846: int samples;
847: static unsigned scaled[1024*512]; // [512*256];
848: int scaled_width, scaled_height;
849:
850: for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
851: ;
852: if (gl_round_down.value && scaled_width > width)
853: scaled_width >>= 1;
854: for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
855: ;
856: if (gl_round_down.value && scaled_height > height)
857: scaled_height >>= 1;
858:
859: scaled_width >>= (int)gl_picmip.value;
860: scaled_height >>= (int)gl_picmip.value;
861:
862: if (scaled_width > gl_max_size.value)
863: scaled_width = gl_max_size.value;
864: if (scaled_height > gl_max_size.value)
865: scaled_height = gl_max_size.value;
866:
867: if (scaled_width * scaled_height > sizeof(scaled)/4)
868: Sys_Error ("GL_LoadTexture: too big");
869:
870: samples = alpha ? gl_alpha_format : gl_solid_format;
871:
872: #if 0
873: if (mipmap)
874: gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
875: else if (scaled_width == width && scaled_height == height)
876: glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
877: else
878: {
879: gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
880: scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
881: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
882: }
883: #else
884:
885: if (scaled_width == width && scaled_height == height)
886: {
887: if (!mipmap)
888: {
889: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
890: goto done;
891: }
892: memcpy (scaled, data, width*height*4);
893: }
894: else
895: GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
896:
897: texels += scaled_width * scaled_height;
898: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
899: if (mipmap)
900: {
901: int miplevel;
902:
903: miplevel = 0;
904: while (scaled_width > 1 || scaled_height > 1)
905: {
906: GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
907: scaled_width >>= 1;
908: scaled_height >>= 1;
909: if (scaled_width < 1)
910: scaled_width = 1;
911: if (scaled_height < 1)
912: scaled_height = 1;
913: miplevel++;
914: texels += scaled_width * scaled_height;
915: glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
916: }
917: }
918: done: ;
919: #endif
920:
921:
922: if (mipmap)
923: {
924: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
925: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
926: }
927: else
928: {
929: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
930: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
931: }
932: }
933:
934: /*
935: ===============
936: GL_Upload8
937: ===============
938: */
939: void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
940: {
941: static unsigned trans[640*480]; // FIXME, temporary
942: int i, s;
943: qboolean noalpha;
944: int p;
945:
946: s = width*height;
947: // if there are no transparent pixels, make it a 3 component
948: // texture even if it was specified as otherwise
949: if (alpha)
950: {
951: noalpha = true;
952: for (i=0 ; i<s ; i++)
953: {
954: p = data[i];
955: if (p == 255)
956: noalpha = false;
957: trans[i] = d_8to24table[p];
958: }
959:
960: if (alpha && noalpha)
961: alpha = false;
962: }
963: else
964: {
965: if (s&3)
966: Sys_Error ("GL_Upload8: s&3");
967: for (i=0 ; i<s ; i+=4)
968: {
969: trans[i] = d_8to24table[data[i]];
970: trans[i+1] = d_8to24table[data[i+1]];
971: trans[i+2] = d_8to24table[data[i+2]];
972: trans[i+3] = d_8to24table[data[i+3]];
973: }
974: }
975:
976: GL_Upload32 (trans, width, height, mipmap, alpha);
977: }
978:
979: /*
980: ================
981: GL_LoadTexture
982: ================
983: */
984: int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
985: {
986: qboolean noalpha;
987: int i, p, s;
988: gltexture_t *glt;
989:
990: // see if the texture is allready present
991: if (identifier[0])
992: {
993: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
994: {
995: if (!strcmp (identifier, glt->identifier))
996: {
997: if (width != glt->width || height != glt->height)
998: Sys_Error ("GL_LoadTexture: cache mismatch");
999: return gltextures[i].texnum;
1000: }
1001: }
1002: }
1003: else
1004: glt = &gltextures[numgltextures];
1005: numgltextures++;
1006:
1007: strcpy (glt->identifier, identifier);
1008: glt->texnum = texture_extension_number;
1009: glt->width = width;
1010: glt->height = height;
1011: glt->mipmap = mipmap;
1012:
1013: GL_Bind(texture_extension_number );
1014:
1015: GL_Upload8 (data, width, height, mipmap, alpha);
1016:
1017: texture_extension_number++;
1018:
1019: return texture_extension_number-1;
1020: }
1021:
1022: /*
1023: ================
1024: GL_LoadPicTexture
1025: ================
1026: */
1027: int GL_LoadPicTexture (qpic_t *pic)
1028: {
1029: return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
1030: }
1031:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.