1 /*
2 Copyright (C) 1997-2001 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
22 
23 #include "gl_local.h"
24 
25 image_t		*draw_chars;
26 
27 // vertex arrays
28 float	tex_array[MAX_ARRAY][2];
29 float	vert_array[MAX_ARRAY][3];
30 float	col_array[MAX_ARRAY][4];
31 
32 extern	qboolean	scrap_dirty;
33 void Scrap_Upload (void);
34 
RefreshFont(void)35 void RefreshFont (void)
36 {
37 
38 	draw_chars = GL_FindImage (va("fonts/%s.pcx", con_font->string), it_pic);
39 	if (!draw_chars)
40 	{
41 		draw_chars = GL_FindImage ("fonts/default.pcx", it_pic);
42 		ri.Cvar_Set( "con_font", "default" );
43 	}
44 
45 	GL_Bind( draw_chars->texnum );
46 
47 	con_font->modified = false;
48 }
49 
50 
51 /*
52 ===============
53 Draw_InitLocal
54 ===============
55 */
Draw_InitLocal(void)56 void Draw_InitLocal (void)
57 {
58 	image_t	*Draw_FindPic (char *name);
59 
60 	// load console characters (don't bilerp characters)
61 	draw_chars = Draw_FindPic ("conchars");
62 
63 	GL_Bind( draw_chars->texnum );
64 
65 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
66 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
67 
68 	//RefreshFont();
69 }
70 
71 
72 
73 /*
74 ================
75 Draw_Char
76 
77 Draws one 8*8 graphics character with 0 being transparent.
78 It can be clipped to the top of the screen to allow the console to be
79 smoothly scrolled off.
80 ================
81 */
82 
CharMapScale(void)83 float	CharMapScale (void)
84 {
85 	return (draw_chars->width/128.0); //current width / original width
86 }
87 
Draw_NoAlphaChar(int x,int y,int num)88 void Draw_NoAlphaChar (int x, int y, int num)
89 {
90 	int				row, col;
91 	float			frow, fcol, size;
92 
93 	num &= 255;
94 
95 	if ( (num&127) == 32 )
96 		return;		// space
97 
98 	if (y <= -8)
99 		return;			// totally off screen
100 
101 	row = num>>4;
102 	col = num&15;
103 
104 	frow = row*0.0625;
105 	fcol = col*0.0625;
106 	size = 0.0625;
107 
108 	GL_Bind (draw_chars->texnum);
109 
110 	qglBegin (GL_QUADS);
111 	qglTexCoord2f (fcol, frow);
112 	qglVertex2f (x, y);
113 	qglTexCoord2f (fcol + size, frow);
114 	qglVertex2f (x+8, y);
115 	qglTexCoord2f (fcol + size, frow + size);
116 	qglVertex2f (x+8, y+8);
117 	qglTexCoord2f (fcol, frow + size);
118 	qglVertex2f (x, y+8);
119 	qglEnd ();
120 }
121 
Draw_Char(int x,int y,int num,int alpha)122 void Draw_Char (int x, int y, int num, int alpha)
123 {
124   Draw_NoAlphaChar(x, y, num);
125 /* we don't need no stinkin' alpha chars...
126 	int				row, col;
127 	float			frow, fcol, size, scale;
128 
129 	num &= 255;
130 
131 
132 	if (alpha >= 254)
133 		alpha = 254;
134 	else if (alpha <= 1)
135 		alpha = 1;
136 
137 	if ( (num&127) == 32 )
138 		return;		// space
139 
140 	if (y <= -8)
141 		return;			// totally off screen
142 
143 	row = num>>4;
144 	col = num&15;
145 
146 	frow = row*0.0625;
147 	fcol = col*0.0625;
148 	size = 0.0625;
149 	scale = 8;
150 
151 	{
152 		qglDisable (GL_ALPHA_TEST);
153 		GL_TexEnv( GL_MODULATE );
154 		qglColor4ub( 255, 255, 255, alpha);
155 		qglEnable( GL_BLEND );
156 		qglDepthMask   (false);
157 	}
158 
159 	GL_Bind(draw_chars->texnum);
160 
161 	qglBegin (GL_QUADS);
162 	qglTexCoord2f (fcol, frow);
163 	qglVertex2f (x, y);
164 	qglTexCoord2f (fcol + size, frow);
165 	qglVertex2f (x+scale, y);
166 	qglTexCoord2f (fcol + size, frow + size);
167 	qglVertex2f (x+scale, y+scale);
168 	qglTexCoord2f (fcol, frow + size);
169 	qglVertex2f (x, y+scale);
170 	qglEnd ();
171 
172 	{
173 		qglDepthMask (true);
174 		GL_TexEnv( GL_REPLACE );
175 		qglDisable ( GL_BLEND );
176 		qglColor4f   (1,1,1,1);
177 
178 		qglEnable (GL_ALPHA_TEST);
179 	}
180 */
181 }
182 
183 
184 /*
185 =============
186 Draw_FindPic
187 =============
188 */
Draw_FindPic(char * name)189 image_t	*Draw_FindPic (char *name)
190 {
191 	image_t *gl;
192 	char	fullname[MAX_QPATH];
193 
194 	if (name[0] != '/' && name[0] != '\\')
195 	{
196 		Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
197 		gl = GL_FindImage (fullname, it_pic);
198 	}
199 	else
200 		gl = GL_FindImage (name+1, it_pic);
201 
202 	return gl;
203 }
204 
205 /*
206 =============
207 Draw_GetPicSize
208 =============
209 */
Draw_GetPicSize(int * w,int * h,char * pic)210 void Draw_GetPicSize (int *w, int *h, char *pic)
211 {
212 	image_t *gl;
213 
214 	gl = Draw_FindPic (pic);
215 	if (!gl)
216 	{
217 		*w = *h = -1;
218 		return;
219 	}
220 	*w = gl->width;
221 	*h = gl->height;
222 }
223 
224 /*
225 =============
226 Draw_StretchPic -- only used for drawing console...
227 =============
228 */
Draw_StretchPic(int x,int y,int w,int h,char * pic,float alpha)229 void Draw_StretchPic (int x, int y, int w, int h, char *pic, float alpha)
230 {
231 	image_t *gl;
232 
233 	gl = Draw_FindPic (pic);
234 	if (!gl)
235 	{
236 		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
237 		return;
238 	}
239 
240 	if (scrap_dirty)
241 		Scrap_Upload ();
242 
243 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
244 		&& !gl->has_alpha)
245 		qglDisable (GL_ALPHA_TEST);
246 
247 	//add alpha support
248 	if (gl->has_alpha || alpha<1)
249 	{
250 		qglDisable (GL_ALPHA_TEST);
251 
252 		GL_Bind( gl->texnum);
253 
254 		GL_TexEnv( GL_MODULATE );
255 		qglColor4f(1,1,1,alpha);
256 		qglEnable( GL_BLEND );
257 		qglDepthMask   (false);
258 	}
259 	else
260 		GL_Bind (gl->texnum);
261 
262 	qglBegin (GL_QUADS);
263 	qglTexCoord2f (gl->sl, gl->tl);
264 	qglVertex2f (x, y);
265 	qglTexCoord2f (gl->sh, gl->tl);
266 	qglVertex2f (x+w, y);
267 	qglTexCoord2f (gl->sh, gl->th);
268 	qglVertex2f (x+w, y+h);
269 	qglTexCoord2f (gl->sl, gl->th);
270 	qglVertex2f (x, y+h);
271 	qglEnd ();
272 
273 	//add alpha support
274 	if (gl->has_alpha || alpha<1)
275 	{
276 		qglDepthMask (true);
277 		GL_TexEnv( GL_REPLACE );
278 		qglDisable ( GL_BLEND );
279 		qglColor4f   (1,1,1,1);
280 
281 		qglEnable (GL_ALPHA_TEST);
282 	}
283 
284 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
285 		&& !gl->has_alpha)
286 		qglEnable (GL_ALPHA_TEST);
287 }
288 
289 /*
290 =============
291 Draw_ScaledPic
292 =============
293 */
294 
Draw_ScaledPic(int x,int y,float scale,float alpha,char * pic)295 void Draw_ScaledPic (int x, int y, float scale, float alpha, char *pic)
296 {
297 	float xoff, yoff;
298 	image_t *gl;
299 
300 	gl = Draw_FindPic (pic);
301 	if (!gl)
302 	{
303 		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
304 		return;
305 	}
306 	if (scrap_dirty)
307 		Scrap_Upload ();
308 
309 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
310 		qglDisable (GL_ALPHA_TEST);
311 
312 	//add alpha support
313 	{
314 		qglDisable (GL_ALPHA_TEST);
315 
316 		qglBindTexture (GL_TEXTURE_2D, gl->texnum);
317 
318 		GL_TexEnv( GL_MODULATE );
319 		qglColor4f(1,1,1, alpha);	//need <1 for trans to work
320 		qglEnable( GL_BLEND );
321 		qglDepthMask   (false);
322 	}
323 
324 	xoff = (gl->width*scale-gl->width)/2;
325 	yoff = (gl->height*scale-gl->height)/2;
326 
327 	GL_Bind (gl->texnum);
328 	qglBegin (GL_QUADS);
329 	qglTexCoord2f (gl->sl, gl->tl);
330 	qglVertex2f (x-xoff, y-yoff);
331 	qglTexCoord2f (gl->sh, gl->tl);
332 	qglVertex2f (x+gl->width+xoff, y-yoff);
333 	qglTexCoord2f (gl->sh, gl->th);
334 	qglVertex2f (x+gl->width+xoff, y+gl->height+yoff);
335 	qglTexCoord2f (gl->sl, gl->th);
336 	qglVertex2f (x-xoff, y+gl->height+yoff);
337 	qglEnd ();
338 
339 	//add alpha support
340 	{
341 		qglDepthMask (true);
342 		GL_TexEnv( GL_REPLACE );
343 		qglDisable ( GL_BLEND );
344 		qglColor4f   (1,1,1,1);
345 
346 		qglEnable (GL_ALPHA_TEST);
347 	}
348 
349 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )  && !gl->has_alpha)
350 		qglEnable (GL_ALPHA_TEST);
351 }
352 
353 /*
354 =============
355 Draw_Pic
356 =============
357 */
Draw_Pic(int x,int y,char * pic)358 void Draw_Pic (int x, int y, char *pic)
359 {
360 	image_t *gl;
361 
362 	gl = Draw_FindPic (pic);
363 	if (!gl)
364 	{
365 		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
366 		return;
367 	}
368 	if (scrap_dirty)
369 		Scrap_Upload ();
370 
371 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
372 		qglDisable (GL_ALPHA_TEST);
373 
374 	//add alpha support
375 	{
376 		qglDisable (GL_ALPHA_TEST);
377 
378 		qglBindTexture (GL_TEXTURE_2D, gl->texnum);
379 
380 		GL_TexEnv( GL_MODULATE );
381 		qglColor4f(1,1,1,0.999);	//need <1 for trans to work
382 		qglEnable( GL_BLEND );
383 		qglDepthMask   (false);
384 	}
385 
386 	GL_Bind (gl->texnum);
387 	qglBegin (GL_QUADS);
388 	qglTexCoord2f (gl->sl, gl->tl);
389 	qglVertex2f (x, y);
390 	qglTexCoord2f (gl->sh, gl->tl);
391 	qglVertex2f (x+gl->width, y);
392 	qglTexCoord2f (gl->sh, gl->th);
393 	qglVertex2f (x+gl->width, y+gl->height);
394 	qglTexCoord2f (gl->sl, gl->th);
395 	qglVertex2f (x, y+gl->height);
396 	qglEnd ();
397 
398 	//add alpha support
399 	{
400 		qglDepthMask (true);
401 		GL_TexEnv( GL_REPLACE );
402 		qglDisable ( GL_BLEND );
403 		qglColor4f   (1,1,1,1);
404 
405 		qglEnable (GL_ALPHA_TEST);
406 	}
407 
408 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )  && !gl->has_alpha)
409 		qglEnable (GL_ALPHA_TEST);
410 }
411 
412 /*
413 =============
414 Draw_TileClear
415 
416 This repeats a 64*64 tile graphic to fill the screen around a sized down
417 refresh window.
418 =============
419 */
Draw_TileClear(int x,int y,int w,int h,char * pic)420 void Draw_TileClear (int x, int y, int w, int h, char *pic)
421 {
422 	image_t	*image;
423 
424 	image = Draw_FindPic (pic);
425 	if (!image)
426 	{
427 		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
428 		return;
429 	}
430 
431 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )  && !image->has_alpha)
432 		qglDisable (GL_ALPHA_TEST);
433 
434 	GL_Bind (image->texnum);
435 	qglBegin (GL_QUADS);
436 	qglTexCoord2f (x/64.0, y/64.0);
437 	qglVertex2f (x, y);
438 	qglTexCoord2f ( (x+w)/64.0, y/64.0);
439 	qglVertex2f (x+w, y);
440 	qglTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
441 	qglVertex2f (x+w, y+h);
442 	qglTexCoord2f ( x/64.0, (y+h)/64.0 );
443 	qglVertex2f (x, y+h);
444 	qglEnd ();
445 
446 	if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )  && !image->has_alpha)
447 		qglEnable (GL_ALPHA_TEST);
448 }
449 
450 
451 /*
452 =============
453 Draw_Fill
454 
455 Fills a box of pixels with a single color
456 =============
457 */
Draw_Fill(int x,int y,int w,int h,int c)458 void Draw_Fill (int x, int y, int w, int h, int c)
459 {
460 	union
461 	{
462 		unsigned	c;
463 		byte		v[4];
464 	} color;
465 
466 	if ( (unsigned)c > 255)
467 		ri.Sys_Error (ERR_FATAL, "Draw_Fill: bad color");
468 
469 	qglDisable (GL_TEXTURE_2D);
470 
471 	color.c = d_8to24table[c];
472 	qglColor3f (color.v[0]*DIV255,
473 		    color.v[1]*DIV255,
474 		    color.v[2]*DIV255);
475 
476 	qglBegin (GL_QUADS);
477 
478 	qglVertex2f (x,y);
479 	qglVertex2f (x+w, y);
480 	qglVertex2f (x+w, y+h);
481 	qglVertex2f (x, y+h);
482 
483 	qglEnd ();
484 	qglColor3f (1,1,1);
485 	qglEnable (GL_TEXTURE_2D);
486 }
487 
488 //=============================================================================
489 
490 /*
491 ================
492 Draw_FadeScreen
493 
494 ================
495 */
Draw_FadeScreen(void)496 void Draw_FadeScreen (void)
497 {
498 	qglEnable (GL_BLEND);
499 	qglDisable (GL_TEXTURE_2D);
500 	qglColor4f (0, 0, 0, 0.8);
501 	qglBegin (GL_QUADS);
502 
503 	qglVertex2f (0,0);
504 	qglVertex2f (vid.width, 0);
505 	qglVertex2f (vid.width, vid.height);
506 	qglVertex2f (0, vid.height);
507 
508 	qglEnd ();
509 	qglColor4f (1,1,1,1);
510 	qglEnable (GL_TEXTURE_2D);
511 	qglDisable (GL_BLEND);
512 }
513 
514 
515 //====================================================================
516 
517 
518 /*
519 =============
520 Draw_StretchRaw
521 =============
522 */
523 extern unsigned	r_rawpalette[256];
524 
Draw_StretchRaw(int x,int y,int w,int h,int cols,int rows,byte * data)525 void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
526 {
527 	unsigned	image32[256*256];
528 	unsigned char image8[256*256];
529 	int			i, j, trows;
530 	byte		*source;
531 	int			frac, fracstep;
532 	float		hscale;
533 	int			row;
534 	float		t;
535 
536 	GL_Bind (0);
537 
538 	if (rows<=256)
539 	{
540 		hscale = 1;
541 		trows = rows;
542 	}
543 	else
544 	{
545 		hscale = rows*DIV256;
546 		trows = 256;
547 	}
548 	t = rows*hscale / 256;
549 
550 	if ( !qglColorTableEXT )
551 	{
552 		unsigned *dest;
553 
554 		for (i=0 ; i<trows ; i++)
555 		{
556 			row = (int)(i*hscale);
557 			if (row > rows)
558 				break;
559 			source = data + cols*row;
560 			dest = &image32[i*256];
561 			fracstep = cols*0x10000*DIV256;
562 			frac = fracstep >> 1;
563 			for (j=0 ; j<256 ; j++)
564 			{
565 				dest[j] = r_rawpalette[source[frac>>16]];
566 				frac += fracstep;
567 			}
568 		}
569 
570 		qglTexImage2D (GL_TEXTURE_2D, 0, gl_tex_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, image32);
571 	}
572 	else
573 	{
574 		unsigned char *dest;
575 
576 		for (i=0 ; i<trows ; i++)
577 		{
578 			row = (int)(i*hscale);
579 			if (row > rows)
580 				break;
581 			source = data + cols*row;
582 			dest = &image8[i*256];
583 			fracstep = cols*0x10000*DIV256;
584 			frac = fracstep >> 1;
585 			for (j=0 ; j<256 ; j++)
586 			{
587 				dest[j] = source[frac>>16];
588 				frac += fracstep;
589 			}
590 		}
591 
592 		qglTexImage2D( GL_TEXTURE_2D,
593 			           0,
594 					   GL_COLOR_INDEX8_EXT,
595 					   256, 256,
596 					   0,
597 					   GL_COLOR_INDEX,
598 					   GL_UNSIGNED_BYTE,
599 					   image8 );
600 	}
601 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
602 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
603 
604 	if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
605 		qglDisable (GL_ALPHA_TEST);
606 
607 	qglBegin (GL_QUADS);
608 	qglTexCoord2f (0, 0);
609 	qglVertex2f (x, y);
610 	qglTexCoord2f (1, 0);
611 	qglVertex2f (x+w, y);
612 	qglTexCoord2f (1, t);
613 	qglVertex2f (x+w, y+h);
614 	qglTexCoord2f (0, t);
615 	qglVertex2f (x, y+h);
616 	qglEnd ();
617 
618 	if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
619 		qglEnable (GL_ALPHA_TEST);
620 }
621 
622