Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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