• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = CVAR2("gl_nobind", "0");
30 cvar_t		gl_max_size = CVAR2("gl_max_size", "1024");
31 cvar_t		gl_picmip = CVAR2("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 
GL_Bind(int texnum)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
Scrap_AllocBlock(int w,int h,int * x,int * y)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 
Scrap_Upload(void)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 
Draw_PicFromWad(char * name)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 */
Draw_CachePic(char * path)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 
Draw_CharToConback(int num,byte * dest)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 */
Draw_TextureMode_f(void)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 */
Draw_Init(void)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< (int) 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 */
Draw_Character(int x,int y,int num)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 #ifdef USE_OPENGLES
520 	DrawQuad(x, y, 8, 8, fcol, frow, size, size);
521 #else
522 	glBegin (GL_QUADS);
523 	glTexCoord2f (fcol, frow);
524 	glVertex2f (x, y);
525 	glTexCoord2f (fcol + size, frow);
526 	glVertex2f (x+8, y);
527 	glTexCoord2f (fcol + size, frow + size);
528 	glVertex2f (x+8, y+8);
529 	glTexCoord2f (fcol, frow + size);
530 	glVertex2f (x, y+8);
531 	glEnd ();
532 #endif
533 }
534 
535 /*
536 ================
537 Draw_String
538 ================
539 */
Draw_String(int x,int y,char * str)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_Alt_String
553 ================
554 */
Draw_Alt_String(int x,int y,char * str)555 void Draw_Alt_String (int x, int y, char *str)
556 {
557 	while (*str)
558 	{
559 		Draw_Character (x, y, (*str) | 0x80);
560 		str++;
561 		x += 8;
562 	}
563 }
564 
Draw_Crosshair(void)565 void Draw_Crosshair(void)
566 {
567 	int x, y;
568 	extern vrect_t		scr_vrect;
569 	unsigned char *pColor;
570 
571 	if (crosshair.value == 2) {
572 		x = scr_vrect.x + scr_vrect.width/2 - 3 + cl_crossx.value;
573 		y = scr_vrect.y + scr_vrect.height/2 - 3 + cl_crossy.value;
574 
575 		glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
576 		pColor = (unsigned char *) &d_8to24table[(byte) crosshaircolor.value];
577 		glColor4ubv ( pColor );
578 		GL_Bind (cs_texture);
579 
580 #ifdef USE_OPENGLES
581         DrawQuad(x - 4, y - 4, 16, 16, 0, 0, 1, 1);
582 #else
583 		glBegin (GL_QUADS);
584 		glTexCoord2f (0, 0);
585 		glVertex2f (x - 4, y - 4);
586 		glTexCoord2f (1, 0);
587 		glVertex2f (x+12, y-4);
588 		glTexCoord2f (1, 1);
589 		glVertex2f (x+12, y+12);
590 		glTexCoord2f (0, 1);
591 		glVertex2f (x - 4, y+12);
592 		glEnd ();
593 #endif
594 
595 		glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
596 	} else if (crosshair.value)
597 		Draw_Character (scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value,
598 			scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value,
599 			'+');
600 }
601 
602 
603 /*
604 ================
605 Draw_DebugChar
606 
607 Draws a single character directly to the upper right corner of the screen.
608 This is for debugging lockups by drawing different chars in different parts
609 of the code.
610 ================
611 */
Draw_DebugChar(char num)612 void Draw_DebugChar (char num)
613 {
614 }
615 
616 /*
617 =============
618 Draw_Pic
619 =============
620 */
Draw_Pic(int x,int y,qpic_t * pic)621 void Draw_Pic (int x, int y, qpic_t *pic)
622 {
623 	glpic_t			*gl;
624 
625 	if (scrap_dirty)
626 		Scrap_Upload ();
627 	gl = (glpic_t *)pic->data;
628 	glColor4f (1,1,1,1);
629 	GL_Bind (gl->texnum);
630 #ifdef USE_OPENGLES
631     DrawQuad(x, y, pic->width, pic->height, gl->sl, gl->tl, gl->sh - gl->sl, gl->th - gl->tl);
632 #else
633 	glBegin (GL_QUADS);
634 	glTexCoord2f (gl->sl, gl->tl);
635 	glVertex2f (x, y);
636 	glTexCoord2f (gl->sh, gl->tl);
637 	glVertex2f (x+pic->width, y);
638 	glTexCoord2f (gl->sh, gl->th);
639 	glVertex2f (x+pic->width, y+pic->height);
640 	glTexCoord2f (gl->sl, gl->th);
641 	glVertex2f (x, y+pic->height);
642 	glEnd ();
643 #endif
644 }
645 
646 /*
647 =============
648 Draw_AlphaPic
649 =============
650 */
Draw_AlphaPic(int x,int y,qpic_t * pic,float alpha)651 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
652 {
653 	glpic_t			*gl;
654 
655 	if (scrap_dirty)
656 		Scrap_Upload ();
657 	gl = (glpic_t *)pic->data;
658 	glDisable(GL_ALPHA_TEST);
659 	glEnable (GL_BLEND);
660 //	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
661 	glCullFace(GL_FRONT);
662 	glColor4f (1,1,1,alpha);
663 	GL_Bind (gl->texnum);
664 #ifdef USE_OPENGLES
665     DrawQuad(x, y, pic->width, pic->height, gl->sl, gl->tl, gl->sh - gl->sl, gl->th - gl->tl);
666 #else
667 	glBegin (GL_QUADS);
668 	glTexCoord2f (gl->sl, gl->tl);
669 	glVertex2f (x, y);
670 	glTexCoord2f (gl->sh, gl->tl);
671 	glVertex2f (x+pic->width, y);
672 	glTexCoord2f (gl->sh, gl->th);
673 	glVertex2f (x+pic->width, y+pic->height);
674 	glTexCoord2f (gl->sl, gl->th);
675 	glVertex2f (x, y+pic->height);
676 	glEnd ();
677 #endif
678 	glColor4f (1,1,1,1);
679 	glEnable(GL_ALPHA_TEST);
680 	glDisable (GL_BLEND);
681 }
682 
Draw_SubPic(int x,int y,qpic_t * pic,int srcx,int srcy,int width,int height)683 void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
684 {
685 	glpic_t			*gl;
686 	float newsl, newtl, newsh, newth;
687 	float oldglwidth, oldglheight;
688 
689 	if (scrap_dirty)
690 		Scrap_Upload ();
691 	gl = (glpic_t *)pic->data;
692 
693 	oldglwidth = gl->sh - gl->sl;
694 	oldglheight = gl->th - gl->tl;
695 
696 	newsl = gl->sl + (srcx*oldglwidth)/pic->width;
697 	newsh = newsl + (width*oldglwidth)/pic->width;
698 
699 	newtl = gl->tl + (srcy*oldglheight)/pic->height;
700 	newth = newtl + (height*oldglheight)/pic->height;
701 
702 	glColor4f (1,1,1,1);
703 	GL_Bind (gl->texnum);
704 #ifdef USE_OPENGLES
705     DrawQuad(x, y, width, height, newsl, newtl, newsh - newsl, newth - newtl);
706 #else
707 	glBegin (GL_QUADS);
708 	glTexCoord2f (newsl, newtl);
709 	glVertex2f (x, y);
710 	glTexCoord2f (newsh, newtl);
711 	glVertex2f (x+width, y);
712 	glTexCoord2f (newsh, newth);
713 	glVertex2f (x+width, y+height);
714 	glTexCoord2f (newsl, newth);
715 	glVertex2f (x, y+height);
716 	glEnd ();
717 #endif
718 }
719 
720 /*
721 =============
722 Draw_TransPic
723 =============
724 */
Draw_TransPic(int x,int y,qpic_t * pic)725 void Draw_TransPic (int x, int y, qpic_t *pic)
726 {
727 
728 	if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
729 		 (unsigned)(y + pic->height) > vid.height)
730 	{
731 		Sys_Error ("Draw_TransPic: bad coordinates");
732 	}
733 
734 	Draw_Pic (x, y, pic);
735 }
736 
737 
738 /*
739 =============
740 Draw_TransPicTranslate
741 
742 Only used for the player color selection menu
743 =============
744 */
Draw_TransPicTranslate(int x,int y,qpic_t * pic,byte * translation)745 void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
746 {
747 	int				v, u, c;
748 	unsigned		trans[64*64], *dest;
749 	byte			*src;
750 	int				p;
751 
752 	GL_Bind (translate_texture);
753 
754 	c = pic->width * pic->height;
755 
756 	dest = trans;
757 	for (v=0 ; v<64 ; v++, dest += 64)
758 	{
759 		src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
760 		for (u=0 ; u<64 ; u++)
761 		{
762 			p = src[(u*pic->width)>>6];
763 			if (p == 255)
764 				dest[u] = p;
765 			else
766 				dest[u] =  d_8to24table[translation[p]];
767 		}
768 	}
769 
770 	glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
771 
772 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
773 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
774 
775 	glColor3f (1,1,1);
776 #ifdef USE_OPENGLES
777 	DrawQuad(x, y, pic->width, pic->height, 0, 0, 1, 1);
778 #else
779 	glBegin (GL_QUADS);
780 	glTexCoord2f (0, 0);
781 	glVertex2f (x, y);
782 	glTexCoord2f (1, 0);
783 	glVertex2f (x+pic->width, y);
784 	glTexCoord2f (1, 1);
785 	glVertex2f (x+pic->width, y+pic->height);
786 	glTexCoord2f (0, 1);
787 	glVertex2f (x, y+pic->height);
788 	glEnd ();
789 #endif
790 }
791 
792 
793 /*
794 ================
795 Draw_ConsoleBackground
796 
797 ================
798 */
Draw_ConsoleBackground(int lines)799 void Draw_ConsoleBackground (int lines)
800 {
801 	char ver[80];
802 	int x, i;
803 	int y;
804 
805 	y = (vid.height * 3) >> 2;
806 	if (lines > y)
807 		Draw_Pic(0, lines-vid.height, conback);
808 	else
809 		Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
810 
811 	// hack the version number directly into the pic
812 //	y = lines-186;
813 	y = lines-14;
814 	if (!cls.download) {
815 #ifdef __linux__
816 		sprintf (ver, "LinuxGL (%4.2f) QuakeWorld", LINUX_VERSION);
817 #else
818 		sprintf (ver, "GL (%4.2f) QuakeWorld", GLQUAKE_VERSION);
819 #endif
820 		x = vid.conwidth - (strlen(ver)*8 + 11) - (vid.conwidth*8/320)*7;
821 		for (i=0 ; i< (int) strlen(ver) ; i++)
822 			Draw_Character (x + i * 8, y, ver[i] | 0x80);
823 	}
824 }
825 
826 
827 /*
828 =============
829 Draw_TileClear
830 
831 This repeats a 64*64 tile graphic to fill the screen around a sized down
832 refresh window.
833 =============
834 */
Draw_TileClear(int x,int y,int w,int h)835 void Draw_TileClear (int x, int y, int w, int h)
836 {
837 	glColor3f (1,1,1);
838 	GL_Bind (*(int *)draw_backtile->data);
839 #ifdef USE_OPENGLES
840 	DrawQuad(x, y, w, h, x/64.0, y/64.0, w/64.0, h/64.0);
841 #else
842 	glBegin (GL_QUADS);
843 	glTexCoord2f (x/64.0, y/64.0);
844 	glVertex2f (x, y);
845 	glTexCoord2f ( (x+w)/64.0, y/64.0);
846 	glVertex2f (x+w, y);
847 	glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
848 	glVertex2f (x+w, y+h);
849 	glTexCoord2f ( x/64.0, (y+h)/64.0 );
850 	glVertex2f (x, y+h);
851 	glEnd ();
852 #endif
853 }
854 
855 
856 /*
857 =============
858 Draw_Fill
859 
860 Fills a box of pixels with a single color
861 =============
862 */
Draw_Fill(int x,int y,int w,int h,int c)863 void Draw_Fill (int x, int y, int w, int h, int c)
864 {
865 	glDisable (GL_TEXTURE_2D);
866 	glColor3f (host_basepal[c*3]/255.0,
867 		host_basepal[c*3+1]/255.0,
868 		host_basepal[c*3+2]/255.0);
869 
870 #ifdef USE_OPENGLES
871 	DrawQuad_NoTex(x, y, w, h);
872 #else
873 	glBegin (GL_QUADS);
874 
875 	glVertex2f (x,y);
876 	glVertex2f (x+w, y);
877 	glVertex2f (x+w, y+h);
878 	glVertex2f (x, y+h);
879 
880 	glEnd ();
881 #endif
882 	glColor3f (1,1,1);
883 	glEnable (GL_TEXTURE_2D);
884 }
885 //=============================================================================
886 
887 /*
888 ================
889 Draw_FadeScreen
890 
891 ================
892 */
Draw_FadeScreen(void)893 void Draw_FadeScreen (void)
894 {
895 	glEnable (GL_BLEND);
896 	glDisable (GL_TEXTURE_2D);
897 	glColor4f (0, 0, 0, 0.8);
898 
899 #ifdef USE_OPENGLES
900 	DrawQuad_NoTex(0, 0, vid.width, vid.height);
901 #else
902 	glBegin (GL_QUADS);
903 
904 	glVertex2f (0,0);
905 	glVertex2f (vid.width, 0);
906 	glVertex2f (vid.width, vid.height);
907 	glVertex2f (0, vid.height);
908 
909 	glEnd ();
910 #endif
911 	glColor4f (1,1,1,1);
912 	glEnable (GL_TEXTURE_2D);
913 	glDisable (GL_BLEND);
914 
915 	Sbar_Changed();
916 }
917 
918 //=============================================================================
919 
920 /*
921 ================
922 Draw_BeginDisc
923 
924 Draws the little blue disc in the corner of the screen.
925 Call before beginning any disc IO.
926 ================
927 */
Draw_BeginDisc(void)928 void Draw_BeginDisc (void)
929 {
930 	if (!draw_disc)
931 		return;
932 #ifdef USE_OPENGLES
933 	// !!! Implement this
934 #else
935 	glDrawBuffer  (GL_FRONT);
936 	Draw_Pic (vid.width - 24, 0, draw_disc);
937 	glDrawBuffer  (GL_BACK);
938 #endif
939 }
940 
941 
942 /*
943 ================
944 Draw_EndDisc
945 
946 Erases the disc icon.
947 Call after completing any disc IO
948 ================
949 */
Draw_EndDisc(void)950 void Draw_EndDisc (void)
951 {
952 }
953 
954 /*
955 ================
956 GL_Set2D
957 
958 Setup as if the screen was 320*200
959 ================
960 */
GL_Set2D(void)961 void GL_Set2D (void)
962 {
963 	glViewport (glx, gly, glwidth, glheight);
964 
965 	glMatrixMode(GL_PROJECTION);
966     glLoadIdentity ();
967 #ifdef USE_OPENGLES
968 	glOrthof (0, vid.width, vid.height, 0, -99999, 99999);
969 #else
970 	glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
971 #endif
972 
973 	glMatrixMode(GL_MODELVIEW);
974     glLoadIdentity ();
975 
976 	glDisable (GL_DEPTH_TEST);
977 	glDisable (GL_CULL_FACE);
978 	glDisable (GL_BLEND);
979 	glEnable (GL_ALPHA_TEST);
980 //	glDisable (GL_ALPHA_TEST);
981 
982 	glColor4f (1,1,1,1);
983 }
984 
985 //====================================================================
986 
987 /*
988 ================
989 GL_FindTexture
990 ================
991 */
GL_FindTexture(char * identifier)992 int GL_FindTexture (char *identifier)
993 {
994 	int		i;
995 	gltexture_t	*glt;
996 
997 	for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
998 	{
999 		if (!strcmp (identifier, glt->identifier))
1000 			return gltextures[i].texnum;
1001 	}
1002 
1003 	return -1;
1004 }
1005 
1006 /*
1007 ================
1008 GL_ResampleTexture
1009 ================
1010 */
GL_ResampleTexture(unsigned * in,int inwidth,int inheight,unsigned * out,int outwidth,int outheight)1011 void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
1012 {
1013 	int		i, j;
1014 	unsigned	*inrow;
1015 	unsigned	frac, fracstep;
1016 
1017 	fracstep = inwidth*0x10000/outwidth;
1018 	for (i=0 ; i<outheight ; i++, out += outwidth)
1019 	{
1020 		inrow = in + inwidth*(i*inheight/outheight);
1021 		frac = fracstep >> 1;
1022 		for (j=0 ; j<outwidth ; j+=4)
1023 		{
1024 			out[j] = inrow[frac>>16];
1025 			frac += fracstep;
1026 			out[j+1] = inrow[frac>>16];
1027 			frac += fracstep;
1028 			out[j+2] = inrow[frac>>16];
1029 			frac += fracstep;
1030 			out[j+3] = inrow[frac>>16];
1031 			frac += fracstep;
1032 		}
1033 	}
1034 }
1035 
1036 /*
1037 ================
1038 GL_Resample8BitTexture -- JACK
1039 ================
1040 */
GL_Resample8BitTexture(unsigned char * in,int inwidth,int inheight,unsigned char * out,int outwidth,int outheight)1041 void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out,  int outwidth, int outheight)
1042 {
1043 	int		i, j;
1044 	unsigned	char *inrow;
1045 	unsigned	frac, fracstep;
1046 
1047 	fracstep = inwidth*0x10000/outwidth;
1048 	for (i=0 ; i<outheight ; i++, out += outwidth)
1049 	{
1050 		inrow = in + inwidth*(i*inheight/outheight);
1051 		frac = fracstep >> 1;
1052 		for (j=0 ; j<outwidth ; j+=4)
1053 		{
1054 			out[j] = inrow[frac>>16];
1055 			frac += fracstep;
1056 			out[j+1] = inrow[frac>>16];
1057 			frac += fracstep;
1058 			out[j+2] = inrow[frac>>16];
1059 			frac += fracstep;
1060 			out[j+3] = inrow[frac>>16];
1061 			frac += fracstep;
1062 		}
1063 	}
1064 }
1065 
1066 /*
1067 ================
1068 GL_MipMap
1069 
1070 Operates in place, quartering the size of the texture
1071 ================
1072 */
GL_MipMap(byte * in,int width,int height)1073 void GL_MipMap (byte *in, int width, int height)
1074 {
1075 	int		i, j;
1076 	byte	*out;
1077 
1078 	width <<=2;
1079 	height >>= 1;
1080 	out = in;
1081 	for (i=0 ; i<height ; i++, in+=width)
1082 	{
1083 		for (j=0 ; j<width ; j+=8, out+=4, in+=8)
1084 		{
1085 			out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
1086 			out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
1087 			out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
1088 			out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
1089 		}
1090 	}
1091 }
1092 
1093 /*
1094 ================
1095 GL_MipMap8Bit
1096 
1097 Mipping for 8 bit textures
1098 ================
1099 */
GL_MipMap8Bit(byte * in,int width,int height)1100 void GL_MipMap8Bit (byte *in, int width, int height)
1101 {
1102 	int		i, j;
1103 	byte	*out;
1104 	unsigned short     r,g,b;
1105 	byte	*at1, *at2, *at3, *at4;
1106 
1107 	height >>= 1;
1108 	out = in;
1109 	for (i=0 ; i<height ; i++, in+=width)
1110 		for (j=0 ; j<width ; j+=2, out+=1, in+=2)
1111 		{
1112 			at1 = (byte *) &d_8to24table[in[0]];
1113 			at2 = (byte *) &d_8to24table[in[1]];
1114 			at3 = (byte *) &d_8to24table[in[width+0]];
1115 			at4 = (byte *) &d_8to24table[in[width+1]];
1116 
1117  			r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
1118  			g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
1119  			b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
1120 
1121 			out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
1122 		}
1123 }
1124 
glTexImage2DHelper(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)1125 void glTexImage2DHelper( GLenum target,
1126 	 GLint level,
1127 	 GLint internalformat,
1128 	 GLsizei width,
1129 	 GLsizei height,
1130 	 GLint border,
1131 	 GLenum format,
1132 	 GLenum type,
1133 	 const GLvoid *pixels )
1134 {
1135 	// In full OpenGL The internalformat can be 1..4, to indicate how many components of the data are valid.
1136 	// OpenGL ES requires the internalformat argument match the format for glTexImage2D.
1137 
1138 	glTexImage2D(target, level, format, width, height, border, format, type, pixels);
1139 }
1140 
1141 /*
1142 ===============
1143 GL_Upload32
1144 ===============
1145 */
GL_Upload32(unsigned * data,int width,int height,qboolean mipmap,qboolean alpha)1146 void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha)
1147 {
1148 	int			samples;
1149 static	unsigned	scaled[1024*512];	// [512*256];
1150 	int			scaled_width, scaled_height;
1151 
1152 	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1153 		;
1154 	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1155 		;
1156 
1157 	scaled_width >>= (int)gl_picmip.value;
1158 	scaled_height >>= (int)gl_picmip.value;
1159 
1160 	if (scaled_width > (int) gl_max_size.value)
1161 		scaled_width = gl_max_size.value;
1162 	if (scaled_height > (int) gl_max_size.value)
1163 		scaled_height = gl_max_size.value;
1164 
1165 	if (scaled_width * scaled_height > (int) sizeof(scaled)/4)
1166 		Sys_Error ("GL_LoadTexture: too big");
1167 
1168 	samples = alpha ? gl_alpha_format : gl_solid_format;
1169 
1170 #if 0
1171 	if (mipmap)
1172 		gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
1173 	else if (scaled_width == width && scaled_height == height)
1174 		glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
1175 	else
1176 	{
1177 		gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
1178 			scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
1179 		glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1180 	}
1181 #else
1182 texels += scaled_width * scaled_height;
1183 
1184 	if (scaled_width == width && scaled_height == height)
1185 	{
1186 		if (!mipmap)
1187 		{
1188 			glTexImage2DHelper (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
1189 			goto done;
1190 		}
1191 		memcpy (scaled, data, width*height*4);
1192 	}
1193 	else
1194 		GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
1195 
1196 	glTexImage2DHelper (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1197 	if (mipmap)
1198 	{
1199 		int		miplevel;
1200 
1201 		miplevel = 0;
1202 		while (scaled_width > 1 || scaled_height > 1)
1203 		{
1204 			GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
1205 			scaled_width >>= 1;
1206 			scaled_height >>= 1;
1207 			if (scaled_width < 1)
1208 				scaled_width = 1;
1209 			if (scaled_height < 1)
1210 				scaled_height = 1;
1211 			miplevel++;
1212 			glTexImage2DHelper (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1213 		}
1214 	}
1215 done: ;
1216 #endif
1217 
1218 
1219 	if (mipmap)
1220 	{
1221 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1222 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1223 	}
1224 	else
1225 	{
1226 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1227 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1228 	}
1229 }
1230 
GL_Upload8_EXT(byte * data,int width,int height,qboolean mipmap,qboolean alpha)1231 void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
1232 {
1233 	int			i, s;
1234 	qboolean	noalpha;
1235 	int			samples;
1236     static	unsigned char scaled[1024*512];	// [512*256];
1237 	int			scaled_width, scaled_height;
1238 
1239 	s = width*height;
1240 	// if there are no transparent pixels, make it a 3 component
1241 	// texture even if it was specified as otherwise
1242 	if (alpha)
1243 	{
1244 		noalpha = true;
1245 		for (i=0 ; i<s ; i++)
1246 		{
1247 			if (data[i] == 255)
1248 				noalpha = false;
1249 		}
1250 
1251 		if (alpha && noalpha)
1252 			alpha = false;
1253 	}
1254 	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
1255 		;
1256 	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
1257 		;
1258 
1259 	scaled_width >>= (int)gl_picmip.value;
1260 	scaled_height >>= (int)gl_picmip.value;
1261 
1262 	if (scaled_width > gl_max_size.value)
1263 		scaled_width = gl_max_size.value;
1264 	if (scaled_height > gl_max_size.value)
1265 		scaled_height = gl_max_size.value;
1266 
1267 	if (scaled_width * scaled_height > (int) sizeof(scaled))
1268 		Sys_Error ("GL_LoadTexture: too big");
1269 
1270 	samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
1271 
1272 	texels += scaled_width * scaled_height;
1273 
1274 	if (scaled_width == width && scaled_height == height)
1275 	{
1276 		if (!mipmap)
1277 		{
1278 #ifdef USE_OPENGLES
1279 			glCompressedTexImage2D (GL_TEXTURE_2D, 0, GL_PALETTE8_RGB8_OES, scaled_width, scaled_height, 0, s, data);
1280 #else
1281 			glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
1282 #endif
1283 			goto done;
1284 		}
1285 		memcpy (scaled, data, width*height);
1286 	}
1287 	else
1288 		GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
1289 
1290 #ifdef USE_OPENGLES
1291 	glCompressedTexImage2D (GL_TEXTURE_2D, 0, GL_PALETTE8_RGB8_OES, scaled_width, scaled_height, 0, s, scaled);
1292 #else
1293 	glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1294 #endif
1295 
1296 	if (mipmap)
1297 	{
1298 		int		miplevel;
1299 
1300 		miplevel = 0;
1301 		while (scaled_width > 1 || scaled_height > 1)
1302 		{
1303 			GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
1304 			scaled_width >>= 1;
1305 			scaled_height >>= 1;
1306 			if (scaled_width < 1)
1307 				scaled_width = 1;
1308 			if (scaled_height < 1)
1309 				scaled_height = 1;
1310 			miplevel++;
1311 #ifdef USE_OPENGLES
1312 			glCompressedTexImage2D (GL_TEXTURE_2D, miplevel, GL_PALETTE8_RGB8_OES, scaled_width, scaled_height, 0, s, scaled);
1313 #else
1314 			glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
1315 #endif
1316 		}
1317 	}
1318 done: ;
1319 
1320 	if (mipmap)
1321 	{
1322 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1323 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1324 	}
1325 	else
1326 	{
1327 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1328 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1329 	}
1330 }
1331 
1332 extern qboolean VID_Is8bit();
1333 
1334 /*
1335 ===============
1336 GL_Upload8
1337 ===============
1338 */
GL_Upload8(byte * data,int width,int height,qboolean mipmap,qboolean alpha)1339 void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
1340 {
1341 static	unsigned	trans[640*480];		// FIXME, temporary
1342 	int			i, s;
1343 	qboolean	noalpha;
1344 	int			p;
1345 
1346 	s = width*height;
1347 	// if there are no transparent pixels, make it a 3 component
1348 	// texture even if it was specified as otherwise
1349 	if (alpha)
1350 	{
1351 		noalpha = true;
1352 		for (i=0 ; i<s ; i++)
1353 		{
1354 			p = data[i];
1355 			if (p == 255)
1356 				noalpha = false;
1357 			trans[i] = d_8to24table[p];
1358 		}
1359 
1360 		if (alpha && noalpha)
1361 			alpha = false;
1362 	}
1363 	else
1364 	{
1365 		if (s&3)
1366 			Sys_Error ("GL_Upload8: s&3");
1367 		for (i=0 ; i<s ; i+=4)
1368 		{
1369 			trans[i] = d_8to24table[data[i]];
1370 			trans[i+1] = d_8to24table[data[i+1]];
1371 			trans[i+2] = d_8to24table[data[i+2]];
1372 			trans[i+3] = d_8to24table[data[i+3]];
1373 		}
1374 	}
1375 
1376 	if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
1377 		GL_Upload8_EXT (data, width, height, mipmap, alpha);
1378 		return;
1379 	}
1380 
1381 	GL_Upload32 (trans, width, height, mipmap, alpha);
1382 }
1383 
1384 /*
1385 ================
1386 GL_LoadTexture
1387 ================
1388 */
GL_LoadTexture(char * identifier,int width,int height,byte * data,qboolean mipmap,qboolean alpha)1389 int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
1390 {
1391 	int			i;
1392 	gltexture_t	*glt;
1393 
1394 	// see if the texture is allready present
1395 	if (identifier[0])
1396 	{
1397 		for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
1398 		{
1399 			if (!strcmp (identifier, glt->identifier))
1400 			{
1401 				if (width != glt->width || height != glt->height)
1402 					Sys_Error ("GL_LoadTexture: cache mismatch");
1403 				return gltextures[i].texnum;
1404 			}
1405 		}
1406 	}
1407 	else
1408 		glt = &gltextures[numgltextures];
1409 	numgltextures++;
1410 
1411 	strcpy (glt->identifier, identifier);
1412 	glt->texnum = texture_extension_number;
1413 	glt->width = width;
1414 	glt->height = height;
1415 	glt->mipmap = mipmap;
1416 
1417 	GL_Bind(texture_extension_number );
1418 
1419 	GL_Upload8 (data, width, height, mipmap, alpha);
1420 
1421 	texture_extension_number++;
1422 
1423 	return texture_extension_number-1;
1424 }
1425 
1426 /*
1427 ================
1428 GL_LoadPicTexture
1429 ================
1430 */
GL_LoadPicTexture(qpic_t * pic)1431 int GL_LoadPicTexture (qpic_t *pic)
1432 {
1433 	return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
1434 }
1435 
1436 /****************************************/
1437 
1438 static GLenum oldtarget = TEXTURE0_SGIS;
1439 
GL_SelectTexture(GLenum target)1440 void GL_SelectTexture (GLenum target)
1441 {
1442 	if (!gl_mtexable)
1443 		return;
1444 #ifdef USE_OPENGLES
1445 	// !!! Implement this.
1446 #else
1447 #ifndef __linux__ // no multitexture under Linux yet
1448 	qglSelectTextureSGIS(target);
1449 #endif
1450 #endif
1451 	if (target == oldtarget)
1452 		return;
1453 	cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
1454 	currenttexture = cnttextures[target-TEXTURE0_SGIS];
1455 	oldtarget = target;
1456 }
1457 
1458 
1459 // OpenGL ES compatible DrawQuad utility
1460 
DrawQuad_NoTex(float x,float y,float w,float h)1461 void DrawQuad_NoTex(float x, float y, float w, float h)
1462 {
1463 	glEnableClientState(GL_VERTEX_ARRAY);
1464 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1465 	float vertex[2*4] = {x,y,x+w,y, x+w, y+h, x, y+h};
1466 	short index[4] = {0, 1, 2, 3};
1467 	glVertexPointer( 2, GL_FLOAT, 0, vertex);
1468 	glDrawElements(GL_TRIANGLE_FAN, 4, GL_SHORT, index);
1469 }
1470 
DrawQuad(float x,float y,float w,float h,float u,float v,float uw,float vh)1471 void DrawQuad(float x, float y, float w, float h, float u, float v, float uw, float vh)
1472 {
1473 	glEnableClientState(GL_VERTEX_ARRAY);
1474 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1475     float texcoord[2*4] = {u, v, u + uw, v, u + uw, v + vh, u, v + vh};
1476 	float vertex[2*4] = {x,y,x+w,y, x+w, y+h, x, y+h};
1477 	unsigned short index[4] = {0, 1, 2, 3};
1478 	glTexCoordPointer( 2, GL_FLOAT, 0, texcoord);
1479 	glVertexPointer( 2, GL_FLOAT, 0, vertex);
1480 	glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, index);
1481 }
1482 
1483 #ifdef USE_OPENGLES
1484 
1485 // Reimplementation of OpenGL functions that are missing in OpenGL ES
1486 
glColor3f(GLfloat r,GLfloat g,GLfloat b)1487 void glColor3f(GLfloat r, GLfloat g, GLfloat b)
1488 {
1489 	glColor4f(r, g, b, 1.0f);
1490 }
1491 
glColor4fv(GLfloat * pColor)1492 void glColor4fv(GLfloat* pColor)
1493 {
1494 	glColor4f(pColor[0], pColor[1], pColor[2], pColor[3]);
1495 }
1496 
glColor4ubv(unsigned char * pColor)1497 void glColor4ubv(unsigned char* pColor)
1498 {
1499 	glColor4f(pColor[0] / 255.0f, pColor[1] / 255.0f, pColor[2] / 255.0f, pColor[3] / 255.0f);
1500 }
1501 
1502 #endif
1503